예제 #1
0
        /// <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);
        }
예제 #2
0
파일: User.cs 프로젝트: aisuru-pw/Sora
        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
            }));
        }
예제 #3
0
파일: Me.cs 프로젝트: Mempler/Sora
        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),
            }));
        }
예제 #4
0
        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()
            );
        }
예제 #5
0
        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);
            }
        }