public async Task ListEventsAsync() { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能获取赛事信息".ErrorEmbed()); } else { var knownEvents = (await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0)).Select(x => x.Value).Where(x => x.Events != null).SelectMany(x => x.Events); var builder = new EmbedBuilder(); builder.Title = "<:page_with_curl:735592941338361897> 赛事"; builder.Color = new Color(random.Next(255), random.Next(255), random.Next(255)); foreach (var @event in knownEvents) { builder.AddField(@event.Name, $"```fix\n{@event.EventId}```\n" + $"```css\n({@event.Guild.Name})```", true); } await ReplyAsync(embed : builder.Build()); } } else { await ReplyAsync(embed : "你没有足够的权限使用该命令".ErrorEmbed()); } }
public async Task ListEventsAsync() { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any event info".ErrorEmbed()); } else { var knownEvents = (await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0)).SelectMany(x => x.Value.Events); var builder = new EmbedBuilder(); builder.Title = "<:page_with_curl:735592941338361897> Events"; builder.Color = new Color(random.Next(255), random.Next(255), random.Next(255)); foreach (var @event in knownEvents) { builder.AddField(@event.Name, $"```fix\n{@event.EventId}```\n" + $"```css\n({@event.Guild.Name})```", true); } await ReplyAsync(embed : builder.Build()); } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
protected async virtual void OnUserDataResolved(string username, ulong userId) { async Task ScrapeHosts() { //Commented out is the code that makes this operate as a mesh network ScrapedInfo = (await HostScraper.ScrapeHosts(Plugin.config.GetHosts(), username, userId, onInstanceComplete: OnIndividualInfoScraped)) .Where(x => x.Value != null) .ToDictionary(s => s.Key, s => s.Value); //Since we're scraping... Let's save the data we learned about the hosts while we're at it var newHosts = Plugin.config.GetHosts().Union(ScrapedInfo.Values.Where(x => x.KnownHosts != null).SelectMany(x => x.KnownHosts)).ToList(); Plugin.config.SaveHosts(newHosts.ToArray()); } //Clear the saved hosts so we don't have stale ones clogging us up Plugin.config.SaveHosts(new CoreServer[] { }); await ScrapeHosts(); if (RescrapeForSecondaryEvents) { await ScrapeHosts(); } OnInfoScraped(); }
public async Task SetScoreChannelAsync(IGuildChannel channel, [Remainder] string paramString) { if (IsAdmin()) { var eventId = paramString.ParseArgs("赛事"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : "用法: `计分频道 #频道 -赛事 \"[赛事ID]\"`\n赛事ID可以通过`赛事列表`命令查找".ErrorEmbed()); } else { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能创建赛事".ErrorEmbed()); } else { var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); if (targetPair.Key != null) { var targetEvent = targetPair.Value.Events.First(x => x.EventId.ToString() == eventId); targetEvent.InfoChannel = new Models.Discord.Channel { Id = channel?.Id ?? 0, Name = channel?.Name ?? "" }; var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : response.Message.SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : "Could not find an event with that ID".ErrorEmbed()); } } } } else { await ReplyAsync(embed : "你没有足够的权限使用该命令".ErrorEmbed()); } }
public async Task SetScoreChannelAsync(IGuildChannel channel, [Remainder] string paramString) { if (IsAdmin()) { var eventId = paramString.ParseArgs("eventId"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : "Usage: `setScoreChannel #channel -eventId \"[event id]\"`\nTo find event ids, please run `listEvents`".ErrorEmbed()); } else { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't add events to it".ErrorEmbed()); } else { var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); if (targetPair.Key != null) { var targetEvent = targetPair.Value.Events.First(x => x.EventId.ToString() == eventId); targetEvent.InfoChannel = new Models.Discord.Channel { Id = channel?.Id ?? 0, Name = channel?.Name ?? "" }; var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : response.Message.SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : "Could not find an event with that ID".ErrorEmbed()); } } } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
public async Task EndEventAsync([Remainder] string paramString = null) { if (IsAdmin()) { //Make server backup /*Logger.Warning($"BACKING UP DATABASE..."); * File.Copy("BotDatabase.db", $"EventDatabase_bak_{DateTime.Now.Day}_{DateTime.Now.Hour}_{DateTime.Now.Minute}_{DateTime.Now.Second}.db"); * Logger.Success("Database backed up succsessfully.");*/ var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能结束赛事信息".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("赛事"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("用法: `结束赛事 -赛事 \"[赛事ID]\"`\n" + "赛事ID可以通过`赛事列表`命令查找").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var response = await server.SendDeleteQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : response.Message.SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } } else { await ReplyAsync(embed : "你没有足够的权限使用该命令".ErrorEmbed()); } }
public async Task EndEventAsync([Remainder] string paramString = null) { if (IsAdmin()) { //Make server backup /*Logger.Warning($"BACKING UP DATABASE..."); * File.Copy("BotDatabase.db", $"EventDatabase_bak_{DateTime.Now.Day}_{DateTime.Now.Hour}_{DateTime.Now.Minute}_{DateTime.Now.Second}.db"); * Logger.Success("Database backed up succsessfully.");*/ var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any event info".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("eventId"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("Usage: `endEvent -eventId \"[event id]\"`\n" + "To find event ids, please run `listEvents`").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var response = await server.SendDeleteQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : response.Message.SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
public async Task ExcelLeaderboardsAsync([Remainder] string paramString) { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any host info".ErrorEmbed()); } else { ExcelPackage.LicenseContext = LicenseContext.NonCommercial; var excel = new ExcelPackage(); var eventId = paramString.ParseArgs("eventId"); var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); foreach (var map in targetEvent.QualifierMaps) { var workSheet = excel.Workbook.Worksheets.Add(map.Beatmap.Name); var scores = (await HostScraper.RequestResponse(targetPair.Key, new Packet(new ScoreRequest { EventId = Guid.Parse(eventId), Parameters = map }), typeof(ScoreRequestResponse), $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0)).SpecificPacket as ScoreRequestResponse; var row = 0; foreach (var score in scores.Scores) { row++; workSheet.SetValue(row, 1, score._Score); workSheet.SetValue(row, 2, score.Username); workSheet.SetValue(row, 3, score.FullCombo ? "FC" : ""); } } await Context.Channel.SendFileAsync(new MemoryStream(excel.GetAsByteArray()), "Leaderboards.xlsx"); } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
public async Task LeaderboardsAsync([Remainder] string paramString) { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any host info".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("eventId"); var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var builder = new EmbedBuilder(); builder.Title = "<:page_with_curl:735592941338361897> Leaderboards"; builder.Color = new Color(random.Next(255), random.Next(255), random.Next(255)); var playerNames = new List <string>(); var playerScores = new List <string>(); foreach (var map in targetEvent.QualifierMaps) { var scores = (await HostScraper.RequestResponse(targetPair.Key, new Packet(new ScoreRequest { EventId = Guid.Parse(eventId), Parameters = map }), typeof(ScoreRequestResponse), $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0)).SpecificPacket as ScoreRequestResponse; builder.AddField(map.Beatmap.Name, $"```\n{string.Join("\n", scores.Scores.Select(x => $"{x.Username}\t{x._Score}\t{(x.FullCombo ? "(Full Combo)" : "")}"))}```", true); } await ReplyAsync(embed : builder.Build()); } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
protected async virtual void OnUserDataResolved(string username, ulong userId) { //Commented out is the code that makes this operate as a mesh network ScrapedInfo = (await HostScraper.ScrapeHosts(Plugin.config.GetHosts(), username, userId, onInstanceComplete: OnIndividualInfoScraped)) .Where(x => x.Value != null) .ToDictionary(s => s.Key, s => s.Value); //This code will make the network operate as a hub and spoke network, since networkauditor.org is the domain of the master server /*ScrapedInfo = (await HostScraper.ScrapeHosts(Plugin.config.GetHosts().Where(x => x.Address.Contains("networkauditor")).ToArray(), username, userId, onInstanceComplete: OnIndividualInfoScraped)) * .Where(x => x.Value != null) * .ToDictionary(s => s.Key, s => s.Value);*/ //Since we're scraping... Let's save the data we learned about the hosts while we're at it var newHosts = ScrapedInfo.Keys.Union(ScrapedInfo.Values.Where(x => x.KnownHosts != null).SelectMany(x => x.KnownHosts)).ToList(); Plugin.config.SaveHosts(newHosts.ToArray()); OnInfoScraped(); }
public async Task DumbLeaderboardsAsync([Remainder] string paramString) { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any host info".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("eventId"); var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var playerNames = new List <string>(); var playerScores = new List <string>(); var leaderboardText = string.Empty; foreach (var map in targetEvent.QualifierMaps) { var scores = (await HostScraper.RequestResponse(targetPair.Key, new Packet(new ScoreRequest { EventId = Guid.Parse(eventId), Parameters = map }), typeof(ScoreRequestResponse), $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0)).SpecificPacket as ScoreRequestResponse; leaderboardText += $"{map.Beatmap.Name}:\n```{string.Join("\n", scores.Scores.Select(x => $"{x.Username} {x._Score} {(x.FullCombo ? "FC" : "")}\n"))}```"; } await ReplyAsync(leaderboardText); } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
public async Task RemoveSongAsync(string songId, [Remainder] string paramString = null) { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any event info".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("eventId"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("Usage: `removeSong -eventId \"[event id]\" -song [song link]`\n" + "To find event ids, please run `listEvents`\n" + "Note: You may also need to include difficulty and modifier info to be sure you remove the right song").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); //Parse the difficulty input, either as an int or a string BeatmapDifficulty difficulty = BeatmapDifficulty.ExpertPlus; string difficultyArg = paramString.ParseArgs("difficulty"); if (difficultyArg != null) { //If the enum conversion doesn't succeed, try it as an int if (!Enum.TryParse(difficultyArg, true, out difficulty)) { await ReplyAsync(embed : ("Could not parse difficulty parameter.\n" + "Usage: `removeSong [songId] [difficulty]`").ErrorEmbed()); return; } } string characteristic = paramString.ParseArgs("characteristic"); characteristic = characteristic ?? "Standard"; GameOptions gameOptions = GameOptions.None; PlayerOptions playerOptions = PlayerOptions.None; //Load up the GameOptions and PlayerOptions foreach (GameOptions o in Enum.GetValues(typeof(GameOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { gameOptions = (gameOptions | o); } } foreach (PlayerOptions o in Enum.GetValues(typeof(PlayerOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { playerOptions = (playerOptions | o); } } //Sanitize input if (songId.StartsWith("https://beatsaver.com/") || songId.StartsWith("https://bsaber.com/")) { //Strip off the trailing slash if there is one if (songId.EndsWith("/")) { songId = songId.Substring(0, songId.Length - 1); } //Strip off the beginning of the url to leave the id songId = songId.Substring(songId.LastIndexOf("/") + 1); } if (songId.Contains("&")) { songId = songId.Substring(0, songId.IndexOf("&")); } //Get the hash for the song var hash = BeatSaverDownloader.GetHashFromID(songId); var song = FindSong(songPool, $"custom_level_{hash.ToUpper()}", characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions); if (song != null) { targetEvent.QualifierMaps = RemoveSong(songPool, $"custom_level_{hash.ToUpper()}", characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions).ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"Removed {song.Beatmap.Name} ({difficulty}) ({characteristic}) from the song list" + $"{(gameOptions != GameOptions.None ? $" with game options: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" with player options: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : $"Specified song does not exist with that difficulty / characteristic / gameOptions / playerOptions ({difficulty} {characteristic} {gameOptions} {playerOptions})".ErrorEmbed()); } } } }
public async Task ListSongsAsync([Remainder] string paramString = null) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't get any event info".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("eventId"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("Usage: `listSongs -eventId \"[event id]\"`\n" + "To find event ids, please run `listEvents`\n").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); var builder = new EmbedBuilder(); builder.Title = "<:page_with_curl:735592941338361897> Song List"; builder.Color = new Color(random.Next(255), random.Next(255), random.Next(255)); var titleField = new EmbedFieldBuilder(); titleField.Name = "Title"; titleField.Value = "```"; titleField.IsInline = true; var difficultyField = new EmbedFieldBuilder(); difficultyField.Name = "Difficulty"; difficultyField.Value = "```"; difficultyField.IsInline = true; var modifierField = new EmbedFieldBuilder(); modifierField.Name = "Modifiers"; modifierField.Value = "```"; modifierField.IsInline = true; foreach (var song in songPool) { titleField.Value += $"\n{song.Beatmap.Name}"; difficultyField.Value += $"\n{song.Beatmap.Difficulty}"; modifierField.Value += $"\n{song.GameplayModifiers.Options}"; } titleField.Value += "```"; difficultyField.Value += "```"; modifierField.Value += "```"; builder.AddField(titleField); builder.AddField(difficultyField); builder.AddField(modifierField); await ReplyAsync(embed : builder.Build()); } }
public async Task AddSongAsync([Remainder] string paramString = null) { if (IsAdmin()) { var eventId = paramString.ParseArgs("eventId"); var songId = paramString.ParseArgs("song"); if (string.IsNullOrEmpty(eventId) || string.IsNullOrEmpty(songId)) { await ReplyAsync(embed : ("Usage: `addSong -eventId \"[event id]\" -song [song link]`\n" + "To find event ids, please run `listEvents`\n" + "Optional parameters: `-difficulty [difficulty]`, `-characteristic [characteristic]` (example: `-characteristic onesaber`), `-[modifier]` (example: `-nofail`)").ErrorEmbed()); return; } //Parse the difficulty input, either as an int or a string BeatmapDifficulty difficulty = BeatmapDifficulty.ExpertPlus; string difficultyArg = paramString.ParseArgs("difficulty"); if (difficultyArg != null) { //If the enum conversion doesn't succeed, try it as an int if (!Enum.TryParse(difficultyArg, true, out difficulty)) { await ReplyAsync(embed : "Could not parse difficulty parameter".ErrorEmbed()); return; } } string characteristic = paramString.ParseArgs("characteristic"); characteristic = characteristic ?? "Standard"; GameOptions gameOptions = GameOptions.None; PlayerOptions playerOptions = PlayerOptions.None; //Load up the GameOptions and PlayerOptions foreach (GameOptions o in Enum.GetValues(typeof(GameOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { gameOptions = (gameOptions | o); } } foreach (PlayerOptions o in Enum.GetValues(typeof(PlayerOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { playerOptions = (playerOptions | o); } } //Sanitize input if (songId.StartsWith("https://beatsaver.com/") || songId.StartsWith("https://bsaber.com/")) { //Strip off the trailing slash if there is one if (songId.EndsWith("/")) { songId = songId.Substring(0, songId.Length - 1); } //Strip off the beginning of the url to leave the id songId = songId.Substring(songId.LastIndexOf("/") + 1); } if (songId.Contains("&")) { songId = songId.Substring(0, songId.IndexOf("&")); } var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "The Server is not running, so we can't can't add songs to it".ErrorEmbed()); } else { //Get the hash for the song var hash = BeatSaverDownloader.GetHashFromID(songId); var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); if (OstHelper.IsOst(hash)) { if (!SongExists(songPool, hash, characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions)) { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = OstHelper.GetOstSongNameFromLevelId(hash), LevelId = hash, Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = difficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"Added: {parameters.Beatmap.Name} ({difficulty}) ({characteristic})" + $"{(gameOptions != GameOptions.None ? $" with game options: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" with player options: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : "Song is already active in the database".ErrorEmbed()); } } else { BeatSaverDownloader.DownloadSong(hash, async(songPath) => { if (songPath != null) { DownloadedSong song = new DownloadedSong(hash); string songName = song.Name; if (!song.GetBeatmapDifficulties(characteristic).Contains(difficulty)) { BeatmapDifficulty nextBestDifficulty = song.GetClosestDifficultyPreferLower(difficulty); if (SongExists(songPool, hash, characteristic, (int)nextBestDifficulty, (int)gameOptions, (int)playerOptions)) { await ReplyAsync(embed: $"{songName} doesn't have {difficulty}, and {nextBestDifficulty} is already in the event".ErrorEmbed()); } else { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = songName, LevelId = $"custom_level_{hash.ToUpper()}", Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = nextBestDifficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed: ($"{songName} doesn't have {difficulty}, using {nextBestDifficulty} instead.\n" + $"Added to the song list" + $"{(gameOptions != GameOptions.None ? $" with game options: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" with player options: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed: response.Message.ErrorEmbed()); } } } else { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = songName, LevelId = $"custom_level_{hash.ToUpper()}", Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = difficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed: ($"{songName} ({difficulty}) ({characteristic}) downloaded and added to song list" + $"{(gameOptions != GameOptions.None ? $" with game options: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" with player options: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed: response.Message.ErrorEmbed()); } } } else { await ReplyAsync(embed: "Could not download song.".ErrorEmbed()); } }); } } } else { await ReplyAsync(embed : "You do not have sufficient permissions to use this command".ErrorEmbed()); } }
public async Task AddSongAsync([Remainder] string paramString = null) { if (IsAdmin()) { var eventId = paramString.ParseArgs("赛事"); var songId = paramString.ParseArgs("歌曲"); if (string.IsNullOrEmpty(eventId) || string.IsNullOrEmpty(songId)) { await ReplyAsync(embed : ("用法: `添加歌曲 -赛事 \"[赛事ID]\" -歌曲 [链接/key]`\n" + "赛事ID可以通过`赛事列表`命令查找\n" + "可选参数: `-难度 [Easy/Normal/Hard/Expert/ExpertPlus]`, `-谱型 [例如: onesaber]`, `-[修改项]` (例如: 不死模式为 `-nofail`)").ErrorEmbed()); return; } //Parse the difficulty input, either as an int or a string BeatmapDifficulty difficulty = BeatmapDifficulty.ExpertPlus; string difficultyArg = paramString.ParseArgs("难度"); if (difficultyArg != null) { //If the enum conversion doesn't succeed, try it as an int if (!Enum.TryParse(difficultyArg, true, out difficulty)) { await ReplyAsync(embed : "请检查难度参数".ErrorEmbed()); return; } } string characteristic = paramString.ParseArgs("谱型"); characteristic = characteristic ?? "Standard"; GameOptions gameOptions = GameOptions.None; PlayerOptions playerOptions = PlayerOptions.None; //Load up the GameOptions and PlayerOptions foreach (GameOptions o in Enum.GetValues(typeof(GameOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { gameOptions = (gameOptions | o); } } foreach (PlayerOptions o in Enum.GetValues(typeof(PlayerOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { playerOptions = (playerOptions | o); } } //Sanitize input if (songId.StartsWith("https://beatsaver.com/") || songId.StartsWith("https://bsaber.com/")) { //Strip off the trailing slash if there is one if (songId.EndsWith("/")) { songId = songId.Substring(0, songId.Length - 1); } //Strip off the beginning of the url to leave the id songId = songId.Substring(songId.LastIndexOf("/") + 1); } if (songId.Contains("&")) { songId = songId.Substring(0, songId.IndexOf("&")); } var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能添加歌曲".ErrorEmbed()); } else { //Get the hash for the song var hash = BeatSaverDownloader.GetHashFromID(songId); var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); if (OstHelper.IsOst(hash)) { if (!SongExists(songPool, hash, characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions)) { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = OstHelper.GetOstSongNameFromLevelId(hash), LevelId = hash, Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = difficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"已添加: {parameters.Beatmap.Name} ({difficulty}) ({characteristic})" + $"{(gameOptions != GameOptions.None ? $" 附加游戏参数: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" 附加玩家参数: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : "歌曲已存在于数据库".ErrorEmbed()); } } else { var songInfo = await BeatSaverDownloader.GetSongInfo(songId); string songName = songInfo.Name; if (!songInfo.HasDifficulty(characteristic, difficulty)) { BeatmapDifficulty nextBestDifficulty = songInfo.GetClosestDifficultyPreferLower(characteristic, difficulty); if (SongExists(songPool, hash, characteristic, (int)nextBestDifficulty, (int)gameOptions, (int)playerOptions)) { await ReplyAsync(embed : $"{songName} 不存在 {difficulty} 难度, 而且 {nextBestDifficulty} 已存在于赛事".ErrorEmbed()); } else { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = songName, LevelId = $"custom_level_{hash.ToUpper()}", Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = nextBestDifficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"{songName} 不存在 {difficulty} 难度, 使用 {nextBestDifficulty} 难度代替。\n" + $"已添加至歌曲列表" + $"{(gameOptions != GameOptions.None ? $" 附加游戏参数: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" 附加玩家参数: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } } else { GameplayParameters parameters = new GameplayParameters { Beatmap = new Beatmap { Name = songName, LevelId = $"custom_level_{hash.ToUpper()}", Characteristic = new Characteristic { SerializedName = characteristic }, Difficulty = difficulty }, GameplayModifiers = new GameplayModifiers { Options = gameOptions }, PlayerSettings = new PlayerSpecificSettings { Options = playerOptions } }; songPool.Add(parameters); targetEvent.QualifierMaps = songPool.ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"{songName} ({difficulty}) ({characteristic}) 已下载并添加至歌曲列表" + $"{(gameOptions != GameOptions.None ? $" 附加游戏参数: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" 附加玩家参数: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } } } } else { await ReplyAsync(embed : "你没有足够的权限使用该命令".ErrorEmbed()); } }
public async Task RemoveSongAsync([Remainder] string paramString = null) { if (IsAdmin()) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能获取赛事信息".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("赛事"); var songId = paramString.ParseArgs("歌曲"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("用法: `删除歌曲 -赛事 \"[赛事ID]\" -歌曲 [链接/key]`\n" + "赛事ID可以通过`赛事列表`命令查找\n" + "注意: 你可能需要在命令种包含难度或者修改项信息来确保你删除的是正确的歌曲").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); //Parse the difficulty input, either as an int or a string BeatmapDifficulty difficulty = BeatmapDifficulty.ExpertPlus; string difficultyArg = paramString.ParseArgs("难度"); if (difficultyArg != null) { //If the enum conversion doesn't succeed, try it as an int if (!Enum.TryParse(difficultyArg, true, out difficulty)) { await ReplyAsync(embed : ("请检查难度参数\n" + "用法: `删除歌曲 [歌曲ID] [难度]`").ErrorEmbed()); return; } } string characteristic = paramString.ParseArgs("谱型"); characteristic = characteristic ?? "Standard"; GameOptions gameOptions = GameOptions.None; PlayerOptions playerOptions = PlayerOptions.None; //Load up the GameOptions and PlayerOptions foreach (GameOptions o in Enum.GetValues(typeof(GameOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { gameOptions = (gameOptions | o); } } foreach (PlayerOptions o in Enum.GetValues(typeof(PlayerOptions))) { if (paramString.ParseArgs(o.ToString()) == "true") { playerOptions = (playerOptions | o); } } //Sanitize input if (songId.StartsWith("https://beatsaver.com/") || songId.StartsWith("https://bsaber.com/")) { //Strip off the trailing slash if there is one if (songId.EndsWith("/")) { songId = songId.Substring(0, songId.Length - 1); } //Strip off the beginning of the url to leave the id songId = songId.Substring(songId.LastIndexOf("/") + 1); } if (songId.Contains("&")) { songId = songId.Substring(0, songId.IndexOf("&")); } //Get the hash for the song var hash = BeatSaverDownloader.GetHashFromID(songId); var song = FindSong(songPool, $"custom_level_{hash.ToUpper()}", characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions); if (song != null) { targetEvent.QualifierMaps = RemoveSong(songPool, $"custom_level_{hash.ToUpper()}", characteristic, (int)difficulty, (int)gameOptions, (int)playerOptions).ToArray(); var response = await server.SendUpdateQualifierEvent(targetPair.Key, targetEvent); if (response.Type == Response.ResponseType.Success) { await ReplyAsync(embed : ($"已从歌曲列表中删除 {song.Beatmap.Name} ({difficulty}) ({characteristic}) " + $"{(gameOptions != GameOptions.None ? $" 附加游戏参数: ({gameOptions})" : "")}" + $"{(playerOptions != PlayerOptions.None ? $" 附加玩家参数: ({playerOptions})" : "!")}").SuccessEmbed()); } else if (response.Type == Response.ResponseType.Fail) { await ReplyAsync(embed : response.Message.ErrorEmbed()); } } else { await ReplyAsync(embed : $"指定歌曲没有相对应 难度/谱型/游戏选项/玩家选项 ({difficulty} {characteristic} {gameOptions} {playerOptions})".ErrorEmbed()); } } } }
public async Task ListSongsAsync([Remainder] string paramString = null) { var server = ServerService.GetServer(); if (server == null) { await ReplyAsync(embed : "服务器不在线,所以不能获取赛事信息".ErrorEmbed()); } else { var eventId = paramString.ParseArgs("赛事"); if (string.IsNullOrEmpty(eventId)) { await ReplyAsync(embed : ("用法: `歌曲列表 -赛事 \"[赛事ID]\"`\n" + "赛事ID可以通过`赛事列表`命令查找\n").ErrorEmbed()); return; } var knownPairs = await HostScraper.ScrapeHosts(server.State.KnownHosts, $"{server.CoreServer.Address}:{server.CoreServer.Port}", 0); var targetPair = knownPairs.FirstOrDefault(x => x.Value.Events.Any(y => y.EventId.ToString() == eventId)); var targetEvent = targetPair.Value.Events.FirstOrDefault(x => x.EventId.ToString() == eventId); var songPool = targetEvent.QualifierMaps.ToList(); var builder = new EmbedBuilder(); builder.Title = "<:page_with_curl:735592941338361897> 歌曲列表"; builder.Color = new Color(random.Next(255), random.Next(255), random.Next(255)); var titleField = new EmbedFieldBuilder(); titleField.Name = "曲名"; titleField.Value = "```"; titleField.IsInline = true; var difficultyField = new EmbedFieldBuilder(); difficultyField.Name = "难度"; difficultyField.Value = "```"; difficultyField.IsInline = true; var modifierField = new EmbedFieldBuilder(); modifierField.Name = "修改项"; modifierField.Value = "```"; modifierField.IsInline = true; foreach (var song in songPool) { titleField.Value += $"\n{song.Beatmap.Name}"; difficultyField.Value += $"\n{song.Beatmap.Difficulty}"; modifierField.Value += $"\n{song.GameplayModifiers.Options}"; } titleField.Value += "```"; difficultyField.Value += "```"; modifierField.Value += "```"; builder.AddField(titleField); builder.AddField(difficultyField); builder.AddField(modifierField); await ReplyAsync(embed : builder.Build()); } }