public async Task ProcessAsync(Sisters.WudiLib.Posts.Message message, HttpApiClient api) { // TODO 验证用户名是否合法 var(success, userInfo) = await OsuApi.GetUserInfoAsync(_userName, OsuMixedApi.Mode.Standard); if (!success) { await api.SendMessageAsync(message.Endpoint, "网络错误。"); return; } if (userInfo == null) { await api.SendMessageAsync(message.Endpoint, "没有此用户。"); return; } var dbResult = await Database.AddNewBindAsync(message.UserId, userInfo.Id, userInfo.Name, "自己绑定", message.UserId, userInfo.Name); if (dbResult.Success) { await api.SendMessageAsync(message.Endpoint, $"成功绑定为{userInfo.Name}。"); } else if (dbResult.Exception is DbUpdateException && dbResult.Exception.InnerException?.Message.Contains("Duplicate", StringComparison.Ordinal) == true) { await api.SendMessageAsync(message.Endpoint, "在已绑定的情况下不允许修改,如需修改请联系 bleatingsheep。"); } else { await api.SendMessageAsync(message.Endpoint, "数据库访问错误。"); FLogger.LogException(dbResult.Exception); } }
public override object CommandHandler(SocketMessage socketMessage, string input, CommandArguments arguments) { if (string.IsNullOrEmpty(input) || input.Length <= 3) { return("Please enter a username to connect to"); } OsuUser osuUser = OsuApi.GetUser(input); if (osuUser == null) { return("Unable to find any user with this username"); } InternalUser internalUser = DatabaseManager.Instance.GetUser(socketMessage.Author.Id); if (string.IsNullOrEmpty(internalUser.OsuUserID)) { internalUser.OsuUserID = osuUser.ID.ToString(); return("Registered '" + osuUser.Name + "' to your profile, " + socketMessage.Author.Mention); } else { internalUser.OsuUserID = osuUser.ID.ToString(); return("Changed connection to '" + osuUser.Name + "' on your profile, " + socketMessage.Author.Mention); } }
public Beatmap(Input input) { if (input.BeatmapId == null) { throw new Exception("No beatmap link provided"); } Task <BeatmapData[]> beatmapRequest = OsuApi.Beatmap(input.BeatmapId, input.ModRequestNumber ?? 0, input.Gamemode); Task <ScoreData[]> leaderboardRequest = OsuApi.Leaderboard(input.BeatmapId, input.Gamemode); Task.WhenAll( beatmapRequest, leaderboardRequest ).Wait(); beatmap = beatmapRequest.Result[0]; leaderboard = leaderboardRequest.Result; CountLeaderboardFullCombo(); difficultyCalculator = new DifficultyCalculator(input.BeatmapId, input.Gamemode, input.ModNumber); difficulty = difficultyCalculator.Calculate(); Embed = CreateEmbed(); }
protected async Task <UserInfo> EnsureGetUserInfo(string name, Bleatingsheep.Osu.Mode mode) { var(success, result) = await OsuApi.GetUserInfoAsync(name, mode); ExecutingException.Ensure(success, "网络错误。"); ExecutingException.Ensure(result != null, "无此用户!"); return(result); }
//Prepare a new session public void PrepareSession(Session session = null) { SessionThread?.Join(); if (session == null) { CurrentSession = new Session { Username = SettingsManager.Instance.Settings["api"]["user"] }; } else { CurrentSession = session; } if (CurrentSession.ReadOnly) { OsuUser currentUserData = null; try { currentUserData = OsuApi.GetUser(CurrentSession.Username, (OsuMode)Enum.Parse(typeof(OsuMode), SettingsManager.Instance.Settings["api"]["gamemode"])); } catch (Exception) { BrowserViewModel.Instance.SendNotification(NotificationType.Danger, StringStorage.Get("Message.UserDataError")); return; } BrowserViewModel.Instance.ApplySession(CurrentSession); BrowserViewModel.Instance.ApplyUser(currentUserData); StopProgressHandler(); BrowserViewModel.Instance.AttachedJavascriptWrapper.Hide("#sessionProgressTime"); BrowserViewModel.Instance.AttachedJavascriptWrapper.Show("#sessionProgressReadonly"); string startDate = DateTimeOffset.FromUnixTimeSeconds(CurrentSession.SessionDate).ToString("MMMM dd yyyy HH:mm:ss"); string endDate = DateTimeOffset.FromUnixTimeSeconds(CurrentSession.SessionEndDate).ToString("MMMM dd yyyy HH:mm:ss"); BrowserViewModel.Instance.AttachedJavascriptWrapper.SetHtml("#sessionProgressReadonlyText", startDate + " to " + endDate); } else { SessionThread = new ExtendedThread(() => OnUpdate(), Convert.ToInt32(SettingsManager.Instance.Settings["api"]["updateRate"])); lastIteration = DateTimeOffset.Now.ToUnixTimeSeconds(); nextIteration = DateTimeOffset.Now.ToUnixTimeSeconds() + SessionThread.SleepTime; StartProgressHandler(); SessionThread.Start(); BrowserViewModel.Instance.AttachedJavascriptWrapper.Hide("#sessionProgressReadonly"); if (SettingsManager.Instance.Settings["display"]["showTimer"] == "true") { BrowserViewModel.Instance.AttachedJavascriptWrapper.Show("#sessionProgressTime"); } } }
public async Task User(CommandContext ctx) { ctx.TriggerTypingAsync(); //add mod data in top plays var input = new Input(ctx.Message); UserData userData = await OsuApi.User(input); var user = new User(input, userData); await ctx.Channel.SendMessageAsync(embed : user.Embed); }
public async Task Best(CommandContext ctx) { ctx.TriggerTypingAsync(); var input = new Input(ctx.Message); ScoreData[] scoreData = await OsuApi.Score(input); var score = new Score(input, scoreData); await ctx.Channel.SendMessageAsync(embed : score.Embed); }
public async Task <bool> Init(string[] args) { var opts = new OptionSet() { { "d|dir=", "Set server storage dir (default: ./)", b => ServerDir = b }, { "s|secret=", "Set client secret (osu!) (required)", s => OsuSecret = s }, { "k|key=", "osu! api v1 key (required)", k => OsuApiKey = k }, { "id=", "osu! client id (default: mine)", id => OsuId = id }, { "t|token=", "discord bot token (required)", t => DiscordToken = t }, { "h|help", "displays help", a => Help = a != null }, { "l|link", "displays bot link and exits", l => Link = l != null }, { "apiRequest=", "does api request", a => Apiv2Req = a }, { "test", "test server only", t => Test = t != null }, { "w|webhook=", "webhook for output", w => WebHook = w }, { "reload", "reload databases", r => Reload = r != null }, }; opts.Parse(args); string botLink = $"https://discordapp.com/oauth2/authorize?client_id={DiscordId}&scope=bot&permissions={DiscordPermissions}"; if (Link) { Console.WriteLine(botLink); return(false); } if (Help || (OsuSecret.Length * OsuApiKey.Length * DiscordToken.Length) == 0) { Console.WriteLine( $@"osu! Miss Analyzer, Discord Bot Edition Bot link: https://discordapp.com/oauth2/authorize?client_id={DiscordId}&scope=bot&permissions={DiscordPermissions}"); opts.WriteOptionDescriptions(Console.Out); return(false); } if (Apiv2Req != null) { OsuApi api2 = new OsuApi(ServerContext.webClient, OsuId, OsuSecret, OsuApiKey); Console.WriteLine(await api2.GetApiv2(Apiv2Req)); return(false); } try { using (var stream = Assembly.GetEntryAssembly().GetManifestResourceStream("OsuMissAnalyzer.Server.Resources.GitCommit.txt")) using (var streamReader = new StreamReader(stream, Encoding.UTF8)) { GitCommit = streamReader.ReadToEnd(); } } catch (Exception) { return(false); } return(true); }
public async Task ProcessAsync(Message message, Sisters.WudiLib.HttpApiClient api) { long id = message.UserId; var(networkSuccess, osuResult) = await DataProvider.GetBindingIdAsync(id); ExecutingException.Ensure(networkSuccess, "无法查询绑定账号。"); ExecutingException.Ensure(osuResult != null, "未绑定 osu! 游戏账号。"); var osuId = osuResult.Value; var recent = (await OsuApi.GetRecentlyAsync(osuId, OsuMixedApi.Mode.Standard, 1)).FirstOrDefault(); if (recent == null) { await api.SendMessageAsync(message.Endpoint, "没打图!"); return; } var reply = new List <string> { "/np 给 bleatingsheep,查询更方便!" }; try { var ppBeatmap = await s_spider.GetBeatmapPlusAsync(recent.BeatmapId); if (ppBeatmap == null) { reply.Add("很抱歉,无法查询 Loved 图。也有可能是 PP+ 没有这张图的数据。"); return; } reply.Add($"https://syrin.me/pp+/b/{ppBeatmap.Id}/"); reply.Add("Stars: " + ppBeatmap.Stars); reply.Add("Aim (Jump): " + ppBeatmap.AimJump); reply.Add("Aim (Flow): " + ppBeatmap.AimFlow); reply.Add("Precision: " + ppBeatmap.Precision); reply.Add("Speed: " + ppBeatmap.Speed); reply.Add("Stamina: " + ppBeatmap.Stamina); reply.Add("Accuracy: " + ppBeatmap.Accuracy); reply.Add("数据来自 PP+。"); } catch (ExceptionPlus) { reply.Add("访问 PP+ 网站失败。"); } finally { await api.SendMessageAsync(message.Endpoint, string.Join("\r\n", reply)); } }
private void GetUserInfoFromOsu() { if (userinfo_locked == 0) { if (bps == null) { var mode = Displayer.Mode; Interlocked.Increment(ref userinfo_locked); userInfo = OsuApi.GetPlayerInfo(Displayer.Playername, mode); Interlocked.Decrement(ref userinfo_locked); } } }
private void GetBpFromOsu() { if (bps_locked == 0) { if (bps == null) { var mode = Displayer.Mode; Interlocked.Increment(ref bps_locked); bps = OsuApi.GetBp(Displayer.Playername, mode); Interlocked.Decrement(ref bps_locked); } } }
public override object CommandHandler(SocketMessage socketMessage, string input, CommandArguments arguments) { ApplyMode(arguments); ApplyPlayer(socketMessage.Author.Id, input); if (_osuUser == null) { return("No user has been found."); } List <OsuPlay> recentPlays = OsuApi.GetUserRecent(_osuUser.Name, _osuMode, 1, true); if (recentPlays == null) { return("" + _osuUser.Name + " has not played in the last 24 hours"); } OsuPlay recentPlay = recentPlays[0]; EmbedBuilder embed = new EmbedBuilder() { Title = "Most recent play by **" + _osuUser.Name + "** in osu!" + _osuMode, Description = "[" + recentPlay.Beatmap.Artist + " - " + recentPlay.Beatmap.Title + " \\[" + recentPlay.Beatmap.DifficultyName + "\\]](https://osu.ppy.sh/beatmaps/" + recentPlay.Beatmap.BeatmapID + ")\n" + "Map status: " + OsuApi.BeatmapStatusEmotes[recentPlay.Beatmap.Status].ToString() + " " + recentPlay.Beatmap.Status.ToString(), ThumbnailUrl = "https://b.ppy.sh/thumb/" + recentPlay.Beatmap.BeatmapSetID + "l.jpg", Fields = new List <EmbedFieldBuilder>() { new EmbedFieldBuilder() { Name = "Beatmap Information", Value = "(" + Mathf.Round(recentPlay.Beatmap.Starrating ?? 0, 2) + "*) CS" + Mathf.Round(recentPlay.Beatmap.MapStats.CS, 2) + " • AR" + Mathf.Round(recentPlay.Beatmap.MapStats.AR, 2) + " • OD" + Mathf.Round(recentPlay.Beatmap.MapStats.OD, 2) + " • HP" + Mathf.Round(recentPlay.Beatmap.MapStats.HP, 2) + "\n" + "Mapped by [" + recentPlay.Beatmap.Mapper + "](https://osu.ppy.sh/users/" + recentPlay.Beatmap.MapperID + ")", IsInline = false }, new EmbedFieldBuilder() { Name = "Play Information", Value = OsuRanks.GetEmojiFromRank(recentPlay.Rank).ToString() + " " + Mathf.Round(recentPlay.Accuracy, 2) + "% **+" + ("" + ((OsuModsShort)recentPlay.Mods).ModParser() + "").Replace(", ", "") + "** • **" + Mathf.Round(recentPlay.Performance.CurrentValue, 2) + "pp** " + recentPlay.MaxCombo + "x/" + recentPlay.Beatmap.MaxCombo + "x " + ((recentPlay.IsFullcombo == "1"?"":"(For FC: **" + Mathf.Round(recentPlay.Performance.CurrentValueIfFC, 2) + "pp**)")) + "\n" + "[" + recentPlay.C300 + "/" + recentPlay.C100 + "/" + recentPlay.C50 + "/" + recentPlay.CMiss + "] • " + recentPlay.Score.FormatNumber(), IsInline = false } }, Footer = new EmbedFooterBuilder() { Text = "Played " + DateTime.Parse(recentPlay.DateAchieved).Humanize(), } }; return(embed); }
public UserTopGenerator(string osuApiKey, MapCacher mapCacher) { if (mapCacher == null) { throw new ArgumentNullException(nameof(mapCacher)); } if (string.IsNullOrEmpty(osuApiKey)) { throw new ArgumentException("osuApiKey is required."); } _osuApi = new OsuApi(osuApiKey); _mapCacher = mapCacher; _collectionManager = new CollectionsManager(_mapCacher.Beatmaps); }
public async Task DiffGraph(CommandContext ctx) { ctx.TriggerTypingAsync(); var input = new Input(ctx.Message); BeatmapData[] beatmapData = await OsuApi.Beatmap(input.BeatmapId ?? input.Page.ToString(), input.ModRequestNumber ?? 0, input.Gamemode); if (beatmapData.Length == 0) { throw new Exception("Beatmap not found"); } var graph = new DifficultyGraph(input, beatmapData[0]); await ctx.Channel.SendFileAsync("graph.png", graph.ToStream()); }
public async Task Link(CommandContext ctx, params string[] nameArgs) { ctx.TriggerTypingAsync(); string osuName = string.Join(" ", nameArgs); if (string.IsNullOrEmpty(osuName)) { throw new Exception("No name provided"); } UserData osuUser = await OsuApi.User(osuName); await Database.SetOsuUser(ctx.Message.Author.Id, osuUser.UserId.ToString()); await ctx.Channel.SendMessageAsync($"{ctx.Message.Author.Mention} has been linked to `{osuName}`"); }
public async Task BadgeWeightedSeedingByUser(CommandContext ctx, int badgeCount, params string[] nameArgs) { int rank = 0; string osuName; if (nameArgs.Length == 1) { int.TryParse(nameArgs[0], out rank); } if (rank == 0) { UserData osuUser; if (nameArgs.Length > 0) { osuName = string.Join(" ", nameArgs).Replace("\"", ""); osuUser = await OsuApi.User(osuName); } else { if (ctx.Message.MentionedUsers.Count > 0) { osuName = await Database.GetOsuUser(ctx.Message.MentionedUsers[0].Id); } else { osuName = await Database.GetOsuUser(ctx.Message.Author.Id); } osuUser = await OsuApi.User(int.Parse(osuName)); } if (string.IsNullOrEmpty(osuName)) { throw new Exception("No username or rank provided"); } await ctx.Channel.SendMessageAsync($"BWS rank for `{osuUser.Username}` with {badgeCount} badges is {Math.Round(Math.Pow(osuUser.PPRank, Math.Pow(0.9937, Math.Pow(badgeCount, 2))))}"); } else { await ctx.Channel.SendMessageAsync($"BWS at rank `{rank}` with {badgeCount} badges is {Math.Round(Math.Pow(rank, Math.Pow(0.9937, Math.Pow(badgeCount, 2))))}"); } }
protected void ApplyPlayer(ulong DiscordID, string input) { _osuUser = null; if (string.IsNullOrEmpty(input)) { InternalUser internalUser = DatabaseManager.Instance.GetUser(DiscordID); if (!string.IsNullOrEmpty(internalUser.OsuUserID)) { _osuUser = OsuApi.GetUser(internalUser.OsuUserID, _osuMode); } } if (_osuUser == null) { string username = HttpUtility.HtmlEncode(input); // Test value _osuUser = OsuApi.GetUser(username, _osuMode); } }
private void OnUpdate() { if (!NetworkManager.Instance.HasConnection()) { BrowserViewModel.Instance.SendNotification(NotificationType.Warning, StringStorage.Get("Message.NoInternet")); return; } //BrowserViewModel.Instance.SendNotification(NotificationType.Success, "Test: session iteration"); OsuUser currentUserData = null; try { currentUserData = OsuApi.GetUser(CurrentSession.Username, (OsuMode)Enum.Parse(typeof(OsuMode), SettingsManager.Instance.Settings["api"]["gamemode"])); } catch (Exception) { BrowserViewModel.Instance.SendNotification(NotificationType.Danger, StringStorage.Get("Message.UserDataError")); } if (currentUserData != null) { if (CurrentSession.InitialData == null) { CurrentSession.InitialData = SessionData.FromUser(currentUserData); } CurrentSession.CurrentData = SessionData.FromUser(currentUserData); CurrentSession.DifferenceData = CurrentSession.CurrentData - CurrentSession.InitialData; BrowserViewModel.Instance.ApplySession(CurrentSession); BrowserViewModel.Instance.ApplyUser(currentUserData); int updateRate = Convert.ToInt32(SettingsManager.Instance.Settings["api"]["updateRate"]); if (updateRate != SessionThread.SleepTime) { SessionThread.SleepTime = updateRate; } } lastIteration = DateTimeOffset.Now.ToUnixTimeSeconds(); nextIteration = DateTimeOffset.Now.ToUnixTimeSeconds() + SessionThread.SleepTime; }
protected async Task <(bool, UserInfo)> GetCachedUserInfo(int id, Bleatingsheep.Osu.Mode mode) { var hasCache = s_cache.TryGetValue <UserInfo>((id, mode), out var cachedInfo); if (hasCache) { return(true, cachedInfo); } var(success, userInfo) = await OsuApi.GetUserInfoAsync(id, mode); if (success) { s_cache.Set((id, mode), userInfo, CacheAvailable); return(true, userInfo); } else { // fail return(default);
public DiscordEmbedBuilder CreateListEmbed() { this.user = OsuApi.User(input).Result; DiscordEmbedBuilder embed = CreateBaseEmbed(); for (int i = input.Page * 5 - 5; i < input.Page * 5; i++) { if (i < scoreList.Length) { ScoreData score = scoreList[i]; int modRequestNumber = OsuHelper.GetModRequestNumber(score.EnabledMods); BeatmapData beatmap = OsuApi.Beatmap(score.BeatmapId, modRequestNumber, input.Gamemode).Result[0]; ppData pp = new PerformanceCalculator(score, beatmap, input.Gamemode).Calculate(); string achievedPp; if (score.Rank.Equals("F") || beatmap.Approved == 4) { achievedPp = $"~~{Math.Round(score.PP > 0 && !input.IsDeltaT ? score.PP : pp.AchievedPp)}pp~~"; } else { achievedPp = Math.Round(score.PP > 0 && !input.IsDeltaT ? score.PP : pp.AchievedPp).ToString() + "pp"; } Dictionary <string, string> data = GetModeData(score, beatmap); embed.AddField($"**{beatmap.Artist} - {beatmap.Title} [{beatmap.Version}]**", $"{GetRankEmoji(score)}{OsuHelper.ParseMods(score.EnabledMods)} {data["accuracy"]} {achievedPp}\n" + $"{data["combo"]} ({data["hits"]})"); } else { break; } } return(embed); }
public ServerBeatmapDb(OsuApi api, string serverDir, bool reload = false) { this.api = api; folder = serverDir; string db = Path.Combine(serverDir, "beatmaps.db"); if (File.Exists(db)) { hashes = JsonConvert.DeserializeObject <Dictionary <string, string> >(File.ReadAllText(db)); Logger.LogAbsolute(Logging.BeatmapsDbSize, hashes.Count); } else { hashes = new Dictionary <string, string>(); } if (reload) { foreach (var file in Directory.EnumerateFiles(Path.Combine(serverDir, "beatmaps"))) { hashes[Beatmap.MD5FromFile(file)] = Path.GetFileNameWithoutExtension(file); } } }
static void Main(string[] args) { Console.WriteLine("Collection Generator"); Console.WriteLine("===================="); Console.WriteLine("WARNING: ALL paths are hardcoded, meaning if you don't change them and recompile this program IT WILL NOT WORK."); //technically it could but eh, better safe than sorry. Console.WriteLine("If you did recompile it with your correct paths then you may continue... (Press enter)"); Console.WriteLine("===================="); Console.ReadLine(); Console.WriteLine("Enter your osu!api key: "); string apiKey = Console.ReadLine(); _api = new OsuApi(apiKey); //grab all maps from 2007 Console.WriteLine("Getting beatmaps. This can take around 5 minutes."); var maps = GetBeatmapsFromYear(2007, false); Console.WriteLine("Generating collections"); OsuFileIo.CollectionLoader.SaveOsdbCollection(GenByYear(maps), @"D:\Kod\kolekcje\ByYear.osdb"); OsuFileIo.CollectionLoader.SaveOsdbCollection(GenByGenreV2(maps), @"D:\Kod\kolekcje\ByGenre.osdb"); OsuFileIo.CollectionLoader.SaveOsdbCollection(GenBulkCollection(maps), @"D:\Kod\kolekcje\Bulk.osdb"); }
public override object CommandHandler(SocketMessage socketMessage, string input, CommandArguments arguments) { ApplyMode(arguments); ApplyPlayer(socketMessage.Author.Id, input); //List<OsuUser> users = APIHelper<List<OsuUser>>.GetData(apiUrl + "get_user?u&k="+apiKey+"&u=" + username); if (_osuUser == null) { return("No user has been found."); } else { EmbedFieldBuilder topplayField = new EmbedFieldBuilder { Name = "Top plays", Value = "No top plays available", IsInline = false }; List <OsuPlay> topPlays = OsuApi.GetUserBest(_osuUser, _osuMode, 3, true); if (topPlays != null && topPlays.Count > 0) { string topPlayString = ""; int i = 0; topPlays.ForEach(play => { i++; string stringified = "**" + i + ". " + "[" + play.Beatmap.Title + " \\[" + play.Beatmap.DifficultyName + "\\]](https://osu.ppy.sh/beatmaps/" + play.Beatmap.BeatmapID + ") +" + ("" + ((OsuModsShort)play.Mods).ModParser() + "").Replace(", ", "") + "** (" + Mathf.Round(play.Beatmap.Starrating ?? 0, 1) + "\\*)\n" + OsuRanks.GetEmojiFromRank(play.Rank).ToString() + " • **" + Mathf.Round(play.Performance.CurrentValue).FormatNumber() + "pp** • " + Mathf.Round(play.Accuracy, 2) + "% • " + play.MaxCombo + (play.Beatmap.MaxCombo != null?"/" + play.Beatmap.MaxCombo:"x") + (play.IsFullcombo == "1" ? " FC" : "") + " • " + play.Score.FormatNumber() + "\n" + "Achieved " + DateTime.Parse(play.DateAchieved).Humanize(); topPlayString += stringified + "\n"; }); topplayField.Value = topPlayString; } EmbedBuilder embed = new EmbedBuilder() { Color = ParentManager.bot.BotColor, Title = "Profile of " + _osuUser.Name, ThumbnailUrl = "https://a.ppy.sh/" + _osuUser.ID, Description = "Showing osu!" + _osuMode + " statistics", Fields = new List <EmbedFieldBuilder>() { new EmbedFieldBuilder() { Name = "Rank", Value = _osuUser.Performance == 0 ? "No PP or inactive" : ("#" + _osuUser.Globalrank.FormatNumber() + " (:flag_" + _osuUser.CountryCode.ToLower() + ": #" + _osuUser.Countryrank.FormatNumber() + ")"), }, new EmbedFieldBuilder() { Name = "Performance", Value = Mathf.Round(_osuUser.Performance).FormatNumber() + "pp", IsInline = true }, new EmbedFieldBuilder() { Name = "Level", Value = Mathf.Floor(_osuUser.Level) + " (" + Mathf.Round((Mathf.Round(_osuUser.Level, 2) - Mathf.Floor(_osuUser.Level)) * 100) + "% to level " + (Mathf.Ceil(_osuUser.Level)) + ")", IsInline = true }, new EmbedFieldBuilder() { Name = "Ranked Score", Value = _osuUser.RankedScore.FormatNumber(), IsInline = true }, new EmbedFieldBuilder() { Name = "Playtime", Value = TimeSpan.FromSeconds(_osuUser.Playtime).Humanize(maxUnit: TimeUnit.Hour), IsInline = true }, new EmbedFieldBuilder() { Name = "Maps played", Value = _osuUser.Playcount.FormatNumber(), IsInline = true }, new EmbedFieldBuilder() { Name = "Total Score", Value = _osuUser.TotalScore.FormatNumber(), IsInline = true }, new EmbedFieldBuilder() { Name = "Ranks", Value = OsuRanks.GetEmojiFromRank("X") + " " + _osuUser.GetCountRankSS().FormatNumber() + " " + "• " + OsuRanks.GetEmojiFromRank("S") + " " + _osuUser.GetCountRankS().FormatNumber() + " " + "• " + OsuRanks.GetEmojiFromRank("A") + " " + _osuUser.GetCountRankA().FormatNumber(), IsInline = false }, topplayField }, Footer = new EmbedFooterBuilder() { Text = "User registered " + DateTime.Parse(_osuUser.Joindate).Humanize() } }; return(embed); } }
private async Task ParseInfoAsync( HttpApiClient api, Endpoint sendBackEndpoint, GroupRequest r, int?osuId = null, TrustedUserInfo userInfo = default) { long userId = r.UserId; string comment = r.Comment; var hints = new List <Message>(); if (!string.IsNullOrEmpty(comment)) { var userNames = OsuHelper.DiscoverUsernames(comment).Where(n => !string.Equals(n, "osu", StringComparison.OrdinalIgnoreCase)); if (osuId != null) { bool success = userInfo != null; // 由于当前未从调用方法处获得上级 API 是否调用成功,在信息不为 null 时默认成功。 if (userInfo == null) { // 可能的重试。 (success, userInfo) = await OsuApi.GetUserInfoAsync(osuId.Value, Mode.Standard).ConfigureAwait(false); } _ = await ProcessApplicantReportAsync(hints, null, (success, userInfo)).ConfigureAwait(false); if (userInfo != null && !userNames.Any(n => string.Equals(userInfo.Name, n, StringComparison.OrdinalIgnoreCase))) {// 绑定不一致 hints.Add(new Message("警告:其绑定的账号与申请不符。")); } } else {// 忽略已绑定的情况,因为可能绑定不一致或者查询失败。 foreach (var name in userNames) { var userTuple = await OsuApi.GetUserInfoAsync(name, Bleatingsheep.Osu.Mode.Standard); //// 我想用 8.0 新语法 //hints.Add(new Message($"{info?.Name ?? name}: " + // $"{(success ? info == null ? "不存在此用户。" : $"PP: {info.Performance}, PC: {info.PlayCount}, TTH: {info.TotalHits}" : "查询失败。")}")); var info = await ProcessApplicantReportAsync(hints, name, userTuple).ConfigureAwait(false); if (info == null) {// 属于没有查到的情况(因为网络问题或者用户不存在),并且之前已经给出错误信息。 continue; } // 自动绑定,在请求消息完全匹配 osu! 用户名的前提下。 if (userNames.Count() == 1 && comment.TrimEnd().EndsWith($"答案:{name}", StringComparison.Ordinal) && info != null) { var bindingResult = await Database.AddNewBindAsync( qq : r.UserId, osuId : info.Id, osuName : info.Name, source : "Auto (Request)", operatorId : r.UserId, operatorName : info.Name).ConfigureAwait(false); if (bindingResult.Success) { hints.Add(new Message($"自动绑定为 {info.Name}")); goto binding_end; } else { hints.Add(new Message($"自动绑定失败。")); } } // 提供绑定并放行的捷径。 if (info?.Performance < 2500) { var ms = new MemoryStream(); using (var bw = new BinaryWriter(ms, Encoding.UTF8, true)) { bw.Write(userId); bw.Write(info.Id); bw.Write(r.Flag); } #pragma warning disable CA5351 // 不要使用损坏的加密算法 using var md5 = MD5.Create(); #pragma warning restore CA5351 // 不要使用损坏的加密算法 ms.Write(md5.ComputeHash(ms.ToArray())); var bytes = ms.ToArray(); var base64 = Convert.ToBase64String(bytes); await api.SendMessageAsync(sendBackEndpoint, $"(占位)绑定为 {info.Name} 并放行:#{base64}#"); } binding_end :; } } } if (hints.Count > 0) { var newLine = new Message("\r\n"); await api.SendMessageAsync(sendBackEndpoint, hints.Aggregate((m1, m2) => { return((m1.Sections.LastOrDefault()?.Type, m2.Sections.FirstOrDefault()?.Type) switch { ("text", "text") => m1 + newLine + m2, _ => m1 + m2, }); })).ConfigureAwait(false);
public async Task <DiscordEmbedBuilder> CreateScoreEmbed() { int requestnumber = OsuHelper.GetModRequestNumber(score.EnabledMods); Task <UserData> userRequest = OsuApi.User(input); Task <BeatmapData[]> beatmapRequest = OsuApi.Beatmap(score.BeatmapId ?? input.BeatmapId, requestnumber, input.Gamemode); Task <ScoreData[]> leaderboardRequest = OsuApi.Leaderboard(score.BeatmapId, input.Gamemode); Task.WhenAll( userRequest, beatmapRequest, leaderboardRequest ).Wait(); user = userRequest.Result; beatmap = beatmapRequest.Result[0]; leaderboard = leaderboardRequest.Result; DiscordEmbedBuilder embed = CreateBaseEmbed(); Dictionary <string, string> data = GetModeData(score, beatmap); string emoji = GetRankEmoji(score); string mods = OsuHelper.ParseMods(score.EnabledMods); ppData pp = new PerformanceCalculator(score, beatmap, input.Gamemode).Calculate(); string achievedPp; if (score.Rank.Equals("F") || beatmap.Approved == 4) { achievedPp = $"~~{Math.Round(score.PP > 0 && !input.IsDeltaT ? score.PP : pp.AchievedPp)}pp~~"; } else { achievedPp = Math.Round(score.PP > 0 && !input.IsDeltaT ? score.PP : pp.AchievedPp).ToString() + "pp"; } var totalTimeSpan = TimeSpan.FromSeconds(beatmap.TotalLength); var hitTimeSpan = TimeSpan.FromSeconds(beatmap.HitLength); string totalLength = string.Format("{0:D2}:{1:D2}", totalTimeSpan.Minutes, totalTimeSpan.Seconds); string hitLength = string.Format("{0:D2}:{1:D2}", hitTimeSpan.Minutes, hitTimeSpan.Seconds); int retryCount = GetRetryCount(); if (retryCount > 0) { embed.Author.Name += $" | Try #{retryCount}"; } embed.WithDescription($"[{beatmap.Artist} - {beatmap.Title} [{beatmap.Version}]](https://osu.ppy.sh/b/{beatmap.BeatmapId})\n" + $"{mods} **{achievedPp}**"); int leaderboardPosition = GetLeaderboardPosition(); if (leaderboardPosition > 0) { embed.Description += $" BM#{leaderboardPosition}"; } embed.AddField("**Score**", $"{emoji} {score.Score.ToString("#,##0")}", true); embed.AddField("**Combo**", data["combo"], true); embed.AddField("**Accuracy**", data["accuracy"], true); embed.AddField("**Hits**", data["hits"], true); if (pp.FullComboPp != 0) { embed.AddField("**PP if FC**", Math.Round(pp.FullComboPp) + "pp", true); } if (pp.ssPp != 0) { embed.AddField("**PP if SS**", Math.Round(pp.ssPp) + "pp", true); } embed.AddField("**Beatmap Values**", $"★{Math.Round(beatmap.DifficultyRating, 2)} **Length**: {totalLength} ({hitLength}) **BPM** {beatmap.bpm}\n" + data["stats"]); embed.WithFooter($"Beatmap by: {beatmap.Creator} | Played on {score.Date}"); Database.SetLastMap(input.DiscordChannelId, beatmap.BeatmapId); return(embed); }
public BeatmapData(string apiKey, IMapDataManager mapCacher) { _mapCacher = mapCacher; _osuApi = new OsuApi(apiKey); }
public async Task ProcessAsync(MessageContext context, HttpApiClient api) { var uid = await EnsureGetBindingIdAsync(context.UserId).ConfigureAwait(false); var apiTask = OsuApi.GetUserInfoAsync(uid, Bleatingsheep.Osu.Mode.Standard).ConfigureAwait(false); using (var page = await Chrome.OpenNewPageAsync().ConfigureAwait(false)) { await page.SetViewportAsync(new ViewPortOptions { DeviceScaleFactor = 2.75, Width = 1440, Height = 900, }).ConfigureAwait(false); await page.GoToAsync($"https://osu.ppy.sh/users/{uid}/osu").ConfigureAwait(false); // wait for load complete const string waitSelector = @"body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2)"; await page.WaitForSelectorAsync(waitSelector).ConfigureAwait(false); const string bestSelector = "body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list"; //ElementHandle bpsElement = await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false); const string buttonSelector = "body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.profile-extra-entries__item > button"; ElementHandle button = await page.QuerySelectorAsync(buttonSelector).ConfigureAwait(false); ElementHandle[]? bpList = default; int maxTryTimes = 4; while (button != null && maxTryTimes-- != 0) { //check bp counts. bpList = await page.QuerySelectorAllAsync(bestSelector + " > div").ConfigureAwait(false); await button.ClickAsync().ConfigureAwait(false); // wait for click complete await page.WaitForSelectorAsync(bestSelector + $" > div:nth-child({bpList.Length})", new WaitForSelectorOptions { Timeout = 8000 /*ms*/ }).ConfigureAwait(false); // seems that bp div adding and button availability changing is NOT synchronized // wait for button availability change await page.WaitForTimeoutAsync(500).ConfigureAwait(false); // requery button button = await page.QuerySelectorAsync(buttonSelector).ConfigureAwait(false); } if (bpList == null) { await api.SendMessageAsync(context.Endpoint, "查询失败。").ConfigureAwait(false); return; } // filter /* * bpList = document.querySelectorAll("body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list > div"); * * bpList.forEach((element) => { var dateTime = element.querySelector("div.play-detail__group.play-detail__group--top > div.play-detail__detail > div > span.play-detail__time > time").getAttribute("datetime"); if (new Date() - Date.parse(dateTime) > 86400000) element.remove(); }) */ await page.EvaluateExpressionAsync(@"bpList = document.querySelectorAll(""body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.osu-layout__section.osu-layout__section--users-extra > div > div > div > div:nth-child(2) > div > div.play-detail-list > div"");").ConfigureAwait(false); await page.EvaluateExpressionAsync(@"bpList.forEach((element) => { var dateTime = element.querySelector(""div.play-detail__group.play-detail__group--top > div.play-detail__detail > div > span.play-detail__time > time"").getAttribute(""datetime""); if (new Date() - Date.parse(dateTime) > 86400000) element.remove(); })").ConfigureAwait(false); // check bpList = await page.QuerySelectorAllAsync(bestSelector + " > div").ConfigureAwait(false); if (bpList.Length == 0) { await api.SendMessageAsync(context.Endpoint, "最近 24 小时没有更新 bp。").ConfigureAwait(false); return; } //screenshot //delete pinned elements await(await page.QuerySelectorAsync("body > div.js-pinned-header.hidden-xs.no-print.nav2-header > div.nav2-header__body").ConfigureAwait(false)).EvaluateFunctionAsync(@"(element) => element.remove()").ConfigureAwait(false); await(await page.QuerySelectorAsync("body > div.osu-layout__section.osu-layout__section--full.js-content.community_profile > div > div > div > div.hidden-xs.page-extra-tabs.page-extra-tabs--profile-page.js-switchable-mode-page--scrollspy-offset").ConfigureAwait(false)).EvaluateFunctionAsync(@"(element) => element.remove()").ConfigureAwait(false); // add extra information await page.EvaluateExpressionAsync($@"document.querySelector(""{bestSelector}"").parentElement.parentElement.querySelector(""h3"").textContent += "" (用户名:"" + {JsonConvert.SerializeObject((await apiTask).Item2?.Name ?? "获取失败")} + "" 查询时间:"" + {JsonConvert.SerializeObject(DateTime.Now.ToString("yyyy-MM-dd H:mm)"))}").ConfigureAwait(false); //ElementHandle printElement = await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false); var printElement = await(await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false)) .EvaluateFunctionHandleAsync("(element) => element.parentNode.parentNode").ConfigureAwait(false) as ElementHandle; printElement ??= await page.QuerySelectorAsync(bestSelector).ConfigureAwait(false); var data = await printElement.ScreenshotDataAsync(new ScreenshotOptions()).ConfigureAwait(false); await api.SendMessageAsync(context.Endpoint, Message.ByteArrayImage(data)).ConfigureAwait(false); } }
public OsuModule(OsuApi api) { _api = api; }
public OsuUser FindUser(string query) { return(OsuApi.GetUser(query)); }
public MatchCost(string matchLink, int warmupCount) { match = OsuApi.Match(matchLink.Substring(37)).Result; this.warmupCount = warmupCount; if (match.Games.Length == 0) { throw new Exception("jij bent echt kankerdom"); } foreach (MultiPlayerGame game in match.Games) { if (warmupCount != 0) { warmupCount--; continue; } foreach (MultiPlayerScore score in game.Scores) { if (score.Score < 5000) { continue; } if (score.Team == 0) { isFfa = true; if (!totalScores.ContainsKey(score.UserId)) { totalScores.Add(score.UserId, new List <double>()); } totalScores[score.UserId].Add(score.Score); } else if (score.Team == 1) { blueTotal += score.Score; if (!blueScores.ContainsKey(score.UserId)) { blueScores.Add(score.UserId, new List <double>()); } blueScores[score.UserId].Add(score.Score); blueScoreCount++; } else if (score.Team == 2) { redTotal += score.Score; if (!redScores.ContainsKey(score.UserId)) { redScores.Add(score.UserId, new List <double>()); } redScores[score.UserId].Add(score.Score); redScoreCount++; } total += score.Score; totalScoreCount++; } mapCount++; } totalAverage = total / totalScoreCount; blueAverage = blueTotal / blueScoreCount; redAverage = redTotal / redScoreCount; if (isFfa) { foreach (KeyValuePair <int, List <double> > playerScores in totalScores) { double cost = 0; foreach (int score in playerScores.Value) { cost += score / totalAverage; } totalCosts.Add(playerScores.Key, new double[] { cost / playerScores.Value.Count * Math.Pow(1.2, Math.Pow(playerScores.Value.Count / mapCount, 0.4)) }); } } else { foreach (KeyValuePair <int, List <double> > playerScores in blueScores) { double cost = 0; double teamcost = 0; foreach (int score in playerScores.Value) { cost += score / totalAverage; teamcost += score / blueAverage; } blueCosts.Add(playerScores.Key, new double[] { cost / playerScores.Value.Count * Math.Pow(1.2, Math.Pow(playerScores.Value.Count / mapCount, 0.4)), teamcost / playerScores.Value.Count * Math.Pow(1.2, Math.Pow(playerScores.Value.Count / mapCount, 0.4)) }); } foreach (KeyValuePair <int, List <double> > playerScores in redScores) { double cost = 0; double teamcost = 0; foreach (int score in playerScores.Value) { cost += score / totalAverage; teamcost += score / redAverage; } redCosts.Add(playerScores.Key, new double[] { cost / playerScores.Value.Count * Math.Pow(1.2, Math.Pow(playerScores.Value.Count / mapCount, 0.4)), teamcost / playerScores.Value.Count * Math.Pow(1.2, Math.Pow(playerScores.Value.Count / mapCount, 0.4)) }); } } }