/// <summary> /// Check if User has Obtained an achievement on this Score Submission /// </summary> /// <param name="factory">Context Factory</param> /// <param name="user">Who tries to Obtain</param> /// <param name="score">Submitted Score</param> /// <param name="map">Beatmap</param> /// <param name="set">Beatmap Set</param> /// <param name="oldLb">Old LeaderBoard</param> /// <param name="newLb">New LeaderBoard</param> /// <returns>Obtained Achievements</returns> public static string ProcessAchievements(SoraDbContext ctx, DbUser user, DbScore score, Beatmap map, BeatmapSet set, DbLeaderboard oldLb, DbLeaderboard newLb ) { var l = new List <Achievement>(); /* * if ((int) newLB.PerformancePointsOsu == 4914) * { * var ach = DBAchievement.GetAchievement(factory, "oog"); * if (!user.AlreadyOptainedAchievement(ach)) * _l.Add(ach); * } */ // Insert custom achievements here. I'll implement a Plugin System later! but this will work for now. // END OF CUSTOM ACHIEVEMENTS var retVal = l.Aggregate("", (current, ach) => current + ach.ToOsuString() + "/"); retVal.TrimEnd('/'); return(retVal); }
public async Task <ActionResult> Get(string userName) { var user = await DbUser.GetDbUser(_context, userName); if (user == null) { return(NotFound(new { code = 410, message = "User not found!" })); } var lb = await DbLeaderboard.GetLeaderboardAsync(_context, user); return(Ok(new { user.Id, user.UserName, Permissions = Permission.From(user.Permissions).Perms, user.Status, user.StatusUntil, user.StatusReason, Achievements = DbAchievement.FromString(_context, user.Achievements ?? ""), Country = "XX", globalRank = lb.GetPosition(_context, PlayMode.Osu), Accuracy = lb.GetAccuracy(_context, PlayMode.Osu), Performance = lb.PerformancePointsOsu, TotalScore = lb.TotalScoreOsu, RankedScore = lb.RankedScoreOsu, PlayCount = lb.PlayCountOsu })); }
public async Task <ActionResult> Get() { if (!User.Identity.IsAuthenticated) { return(Ok(new { authentication = "basic" })); } var user = await DbUser.GetDbUser(_context, int.Parse(User.Identity.Name)); if (user == null) { return(Ok(new { authentication = "basic" })); } var lb = await DbLeaderboard.GetLeaderboardAsync(_context, user); return(Ok(new { user.Id, user.UserName, user.Permissions, user.Status, user.StatusUntil, user.StatusReason, Achievements = DbAchievement.FromString(_context, user.Achievements ?? ""), Country = "XX", globalRank = lb.GetPosition(_context, PlayMode.Osu), Accuracy = lb.GetAccuracy(_context, PlayMode.Osu), Performance = lb.PerformancePointsOsu, TotalScore = lb.TotalScoreOsu, RankedScore = lb.RankedScoreOsu, PlayCount = lb.PlayCountOsu, Followers = await DbFriend.GetFollowerCount(_context, user.Id), })); }
public async Task<IActionResult> PostSubmitModular() { if (!Directory.Exists("data/replays")) Directory.CreateDirectory("data/replays"); string encScore = Request.Form["score"]; string iv = Request.Form["iv"]; string osuver = Request.Form["osuver"]; string passwd = Request.Form["pass"]; var (pass, score) = ScoreSubmissionParser.ParseScore(encScore, iv, osuver); var dbUser = await DbUser.GetDbUser(_ctx, score.UserName); if (dbUser == null) return Ok("error: pass"); if (!dbUser.IsPassword(passwd)) return Ok("error: pass"); if (!_ps.TryGet(dbUser.Id, out var pr)) return Ok("error: pass"); // User not logged in in Bancho! if (!pass || !RankedMods.IsRanked(score.Mods)) { var lb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbUser); lb.IncreasePlaycount(score.PlayMode); lb.IncreaseScore((ulong) score.TotalScore, false, score.PlayMode); await lb.SaveChanges(_ctx); // Send to other People await _ev.RunEvent( EventType.BanchoUserStatsRequest, new BanchoUserStatsRequestArgs {UserIds = new List<int> {score.Id}, Pr = pr} ); // Send to self await _ev.RunEvent( EventType.BanchoSendUserStatus, new BanchoSendUserStatusArgs {Status = pr.Status, Pr = pr} ); return Ok("Thanks for your hard work! onii-chyan~"); // even though, we're Sora, we can still be cute! } var replayFileData = Request.Form.Files.GetFile("score"); var dbScore = new DbScore { Accuracy = score.ComputeAccuracy(), Count100 = score.Count100, Count50 = score.Count50, Count300 = score.Count300, Date = score.Date, Mods = score.Mods, CountGeki = score.CountGeki, CountKatu = score.CountKatu, CountMiss = score.CountMiss, FileMd5 = score.FileMd5, MaxCombo = score.MaxCombo, PlayMode = score.PlayMode, ScoreOwner = dbUser, TotalScore = score.TotalScore, UserId = dbUser.Id }; await _pisstaube.DownloadBeatmapAsync(dbScore.FileMd5); await using (var m = new MemoryStream()) { replayFileData.CopyTo(m); m.Position = 0; dbScore.ReplayMd5 = Hex.ToHex(Crypto.GetMd5(m)) ?? string.Empty; if (!string.IsNullOrEmpty(dbScore.ReplayMd5)) { await using var replayFile = System.IO.File.Create($"data/replays/{dbScore.ReplayMd5}"); m.Position = 0; m.WriteTo(replayFile); m.Close(); replayFile.Close(); } } dbScore.PerformancePoints = dbScore.ComputePerformancePoints(); var oldScore = await DbScore.GetLatestScore(_ctx, dbScore); var oldLb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbScore.ScoreOwner); var oldStdPos = oldLb.GetPosition(_ctx, dbScore.PlayMode); var oldAcc = oldLb.GetAccuracy(_ctx, dbScore.PlayMode); double newAcc; if (oldScore != null && oldScore.TotalScore <= dbScore.TotalScore) { _ctx.Remove(oldScore); System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}"); await DbScore.InsertScore(_ctx, dbScore); } else if (oldScore == null) { await DbScore.InsertScore(_ctx, dbScore); } else { System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}"); } var newlb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbScore.ScoreOwner); newlb.IncreasePlaycount(dbScore.PlayMode); newlb.IncreaseScore((ulong) dbScore.TotalScore, true, dbScore.PlayMode); newlb.IncreaseScore((ulong) dbScore.TotalScore, false, dbScore.PlayMode); newlb.UpdatePp(_ctx, dbScore.PlayMode); await newlb.SaveChanges(_ctx); var newStdPos = newlb.GetPosition(_ctx, dbScore.PlayMode); newAcc = newlb.GetAccuracy(_ctx, dbScore.PlayMode); var newScore = await DbScore.GetLatestScore(_ctx, dbScore); var set = await _pisstaube.FetchBeatmapSetAsync(dbScore.FileMd5); var bm = set?.ChildrenBeatmaps.First(x => x.FileMD5 == dbScore.FileMd5) ?? new Beatmap(); ulong oldRankedScore; ulong newRankedScore; double oldPp; double newPp; switch (dbScore.PlayMode) { case PlayMode.Osu: oldRankedScore = oldLb.RankedScoreOsu; newRankedScore = newlb.RankedScoreOsu; oldPp = oldLb.PerformancePointsOsu; newPp = newlb.PerformancePointsOsu; break; case PlayMode.Taiko: oldRankedScore = oldLb.RankedScoreTaiko; newRankedScore = newlb.RankedScoreTaiko; oldPp = oldLb.PerformancePointsTaiko; newPp = newlb.PerformancePointsTaiko; break; case PlayMode.Ctb: oldRankedScore = oldLb.RankedScoreCtb; newRankedScore = newlb.RankedScoreCtb; oldPp = oldLb.PerformancePointsCtb; newPp = newlb.PerformancePointsCtb; break; case PlayMode.Mania: oldRankedScore = oldLb.RankedScoreMania; newRankedScore = newlb.RankedScoreMania; oldPp = oldLb.PerformancePointsMania; newPp = newlb.PerformancePointsMania; break; default: return Ok(""); } var newScorePosition = newScore != null ? await newScore.Position(_ctx) : 0; var oldScorePosition = oldScore != null ? await oldScore.Position(_ctx) : 0; if (newScorePosition == 1) _sora.SendMessage( $"[http://{_config.Server.ScreenShotHostname}/{dbScore.ScoreOwner.Id} {dbScore.ScoreOwner.UserName}] " + $"has reached #1 on [https://osu.ppy.sh/b/{bm.BeatmapID} {set?.Title} [{bm.DiffName}]] " + $"using {ModUtil.ToString(newScore.Mods)} " + $"Good job! +{newScore.PerformancePoints:F}PP", "#announce", false ); Logger.Info( $"{LCol.RED}{dbScore.ScoreOwner.UserName}", $"{LCol.PURPLE}( {dbScore.ScoreOwner.Id} ){LCol.WHITE}", $"has just submitted a Score! he earned {LCol.BLUE}{newScore?.PerformancePoints:F}PP", $"{LCol.WHITE}with an Accuracy of {LCol.RED}{newScore?.Accuracy * 100:F}", $"{LCol.WHITE}on {LCol.YELLOW}{set?.Title} [{bm.DiffName}]", $"{LCol.WHITE}using {LCol.BLUE}{ModUtil.ToString(newScore?.Mods ?? Mod.None)}" ); var bmChart = new Chart( "beatmap", "Beatmap Ranking", $"https://osu.ppy.sh/b/{bm.BeatmapID}", oldScorePosition, newScorePosition, oldScore?.MaxCombo ?? 0, newScore?.MaxCombo ?? 0, oldScore?.Accuracy * 100 ?? 0, newScore?.Accuracy * 100 ?? 0, (ulong) (oldScore?.TotalScore ?? 0), (ulong) (newScore?.TotalScore ?? 0), oldScore?.PerformancePoints ?? 0, newScore?.PerformancePoints ?? 0, newScore?.Id ?? 0 ); var overallChart = new Chart( "overall", "Global Ranking", $"https://osu.ppy.sh/u/{dbUser.Id}", (int) oldStdPos, (int) newStdPos, 0, 0, oldAcc * 100, newAcc * 100, oldRankedScore, newRankedScore, oldPp, newPp, newScore?.Id ?? 0, AchievementProcessor.ProcessAchievements( _ctx, dbScore.ScoreOwner, score, bm, set, oldLb, newlb ) ); pr["LB"] = newlb; pr.Stats.Accuracy = (float) newlb.GetAccuracy(_ctx, score.PlayMode); pr.Stats.Position = newlb.GetPosition(_ctx, score.PlayMode); switch (score.PlayMode) { case PlayMode.Osu: pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsOsu; pr.Stats.TotalScore = (ushort) newlb.TotalScoreOsu; pr.Stats.RankedScore = (ushort) newlb.RankedScoreOsu; pr.Stats.PlayCount = (ushort) newlb.PlayCountOsu; break; case PlayMode.Taiko: pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsTaiko; pr.Stats.TotalScore = (ushort) newlb.TotalScoreTaiko; pr.Stats.RankedScore = (ushort) newlb.RankedScoreTaiko; pr.Stats.PlayCount = (ushort) newlb.PlayCountTaiko; break; case PlayMode.Ctb: pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsCtb; pr.Stats.TotalScore = (ushort) newlb.TotalScoreCtb; pr.Stats.RankedScore = (ushort) newlb.RankedScoreCtb; pr.Stats.PlayCount = (ushort) newlb.PlayCountCtb; break; case PlayMode.Mania: pr.Stats.PerformancePoints = (ushort) newlb.PerformancePointsMania; pr.Stats.TotalScore = (ushort) newlb.TotalScoreMania; pr.Stats.RankedScore = (ushort) newlb.RankedScoreMania; pr.Stats.PlayCount = (ushort) newlb.PlayCountMania; break; } // Send to other People await _ev.RunEvent( EventType.BanchoUserStatsRequest, new BanchoUserStatsRequestArgs {UserIds = new List<int> {score.Id}, Pr = pr} ); // Send to self await _ev.RunEvent( EventType.BanchoSendUserStatus, new BanchoSendUserStatusArgs {Status = pr.Status, Pr = pr} ); return Ok( $"beatmapId:{bm.BeatmapID}|beatmapSetId:{bm.ParentSetID}|beatmapPlaycount:0|beatmapPasscount:0|approvedDate:\n\n" + bmChart.ToOsuString() + "\n" + overallChart.ToOsuString() ); }
public async Task OnLoginRequest(BanchoLoginRequestArgs args) { try { var sw = new Stopwatch(); sw.Start(); var loginData = LoginParser.ParseLogin(args.Reader); if (loginData == null) { Exception(args.Writer); return; } var cacheKey = $"sora:user:{loginData.GetHashCode()}"; if (!_cache.TryGet(cacheKey, out Presence presence)) { var dbUser = await DbUser.GetDbUser(_ctx, loginData.Username); if (dbUser == null) { LoginFailed(args.Writer); return; } if (!dbUser.IsPassword(loginData.Password)) { _logger.Log(LogLevel.Warning, $"{LCOL.RED}{dbUser.UserName} " + $"{LCOL.PURPLE}({dbUser.Id}) " + $"{LCOL.RED}Failed {LCOL.WHITE}to Login!"); LoginFailed(args.Writer); return; } if (args.IpAddress != "127.0.0.1" && args.IpAddress != "0.0.0.0") { try { var data = Localisation.GetData(args.IpAddress); args.Pr.Info.Longitude = data.Location.Longitude ?? 0; args.Pr.Info.Latitude = data.Location.Latitude ?? 0; args.Pr.Info.CountryId = Localisation.StringToCountryId(data.Country.IsoCode); } catch { // Ignored.. doesn't matter too much } } args.Pr.User = dbUser; args.Pr.Info.TimeZone = (byte)loginData.Timezone; var lb = await DbLeaderboard.GetLeaderboardAsync(_ctx, dbUser); args.Pr["LB"] = lb; args.Pr.Stats.TotalScore = lb.TotalScoreOsu; args.Pr.Stats.RankedScore = lb.RankedScoreOsu; args.Pr.Stats.PerformancePoints = (ushort)lb.PerformancePointsOsu; args.Pr.Stats.PlayCount = (uint)lb.PlayCountOsu; args.Pr.Stats.Accuracy = (float)lb.GetAccuracy(_ctx, PlayMode.Osu); args.Pr.Stats.Position = lb.GetPosition(_ctx, PlayMode.Osu); //args.pr["BLOCK_NON_FRIENDS_DM"] = loginData.BlockNonFriendDMs; _cache.Set(cacheKey, args.Pr, TimeSpan.FromMinutes(30)); } else { var t = args.Pr.Token; args.Pr = presence; args.Pr.Token = t; } if (_pcs.TryGet(args.Pr.User.Id, out var oldPresence)) { oldPresence.ActiveMatch?.Leave(args.Pr); oldPresence.Spectator?.Leave(args.Pr); _pcs.Leave(oldPresence); } _pcs.Join(args.Pr); Success(args.Writer, args.Pr.User.Id); args.Pr.Push(new ProtocolNegotiation()); args.Pr.Push(new UserPresence(args.Pr)); args.Pr.Push(new HandleUpdate(args.Pr)); args.Pr.Info.ClientPermission = LoginPermissions.User; if (args.Pr.User.Permissions == Permission.GROUP_DONATOR) { args.Pr.Info.ClientPermission |= LoginPermissions.Supporter; } if (args.Pr.User.Permissions == Permission.GROUP_ADMIN) { args.Pr.Info.ClientPermission |= LoginPermissions.BAT | LoginPermissions.Administrator | LoginPermissions.Moderator; } if (args.Pr.User.Permissions == Permission.GROUP_DEVELOPER) { args.Pr.Info.ClientPermission |= LoginPermissions.Developer; } if (!args.Pr.User.Permissions.HasPermission(Permission.GROUP_DONATOR)) { if (_cfg.Server.FreeDirect) { args.Pr.Push(new LoginPermission(LoginPermissions.User | LoginPermissions.Supporter | args.Pr.Info.ClientPermission)); } } else { args.Pr.Push(new LoginPermission(args.Pr.Info.ClientPermission)); } args.Pr.Push(new FriendsList(DbFriend.GetFriends(_ctx, args.Pr.User.Id).ToList())); args.Pr.Push(new PresenceBundle(_pcs.GetUserIds(args.Pr).ToList())); foreach (var chanAuto in _cs.ChannelsAutoJoin) { if ((chanAuto.Status & ChannelStatus.AdminOnly) != 0 && args.Pr.User.Permissions == Permission.ADMIN_CHANNEL) { args.Pr.Push(new ChannelAvailableAutojoin(chanAuto)); } else if ((chanAuto.Status & ChannelStatus.AdminOnly) == 0) { args.Pr.Push(new ChannelAvailableAutojoin(chanAuto)); } args.Pr.Push(new ChannelJoinSuccess(chanAuto)); chanAuto.Join(args.Pr); } foreach (var channel in _cs.Channels) { if ((channel.Status & ChannelStatus.AdminOnly) != 0 && args.Pr.User.Permissions == Permission.ADMIN_CHANNEL) { args.Pr.Push(new ChannelAvailable(channel)); } else if ((channel.Status & ChannelStatus.AdminOnly) == 0) { args.Pr.Push(new ChannelAvailable(channel)); } } _pcs.Push(new PresenceSingle(args.Pr.User.Id)); _pcs.Join(args.Pr); args.Pr.WritePackets(args.Writer.BaseStream); sw.Stop(); _logger.Log(LogLevel.Debug, "Login Time:\nMS: ", sw.Elapsed.TotalMilliseconds); _logger.Log(LogLevel.Information, $"{LCOL.RED}{args.Pr.User.UserName} {LCOL.PURPLE}( {args.Pr.User.Id} ) {LCOL.WHITE}has logged in!" ); args.Pr["LAST_PONG"] = DateTime.Now; } catch (Exception ex) { Logger.Err(ex); Exception(args.Writer); } }