/// <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 Sora(SoraDbContext ctx, IServiceProvider provider, PresenceService ps, ChannelService cs, EventManager ev ) { _provider = provider; _ctx = ctx; _ps = ps; _cs = cs; _ev = ev; #region DEFAULT COMMANDS RegisterCommandClass <RestrictCommand>(); RegisterCommandClass <DebugCommand>(); #endregion ctx.Migrate(); // this will fail if bot already exists! DbUser.RegisterUser(_ctx, Permission.From(Permission.GROUP_ADMIN), "Aisuru", "*****@*****.**", Crypto.RandomString(32), false, PasswordVersion.V2, 100); _dbUser = DbUser.GetDbUser(ctx, 100).Result; }
public async Task <IActionResult> GetSearchDirect( [FromQuery(Name = "m")] int playMode, [FromQuery(Name = "r")] int rankedStatus, [FromQuery(Name = "p")] int page, [FromQuery(Name = "q")] string query, [FromQuery(Name = "u")] string userName, [FromQuery(Name = "h")] string pass, [FromServices] SoraDbContext ctx, [FromServices] Pisstaube pisstaube ) { Response.ContentType = "text/plain"; var user = await DbUser.GetDbUser(ctx, userName); if (user == null) { return(Ok("err: pass")); } if (!user.IsPassword(pass)) { return(Ok("err: pass")); } var searchResult = await pisstaube.SearchDirectAsync(query, rankedStatus, playMode, page); return(Ok(searchResult)); // this no longer needs to be cached... }
public async Task <IActionResult> GetDirectNp( [FromQuery(Name = "s")] int setId, [FromQuery(Name = "b")] int beatmapId, [FromQuery(Name = "u")] string userName, [FromQuery(Name = "h")] string pass, [FromServices] SoraDbContext ctx, [FromServices] Pisstaube pisstaube ) { Response.ContentType = "text/plain"; var user = await DbUser.GetDbUser(ctx, userName); if (user == null) { return(Ok("err: pass")); } if (!user.IsPassword(pass)) { return(Ok("err: pass")); } return(Ok(await(setId != 0 ? pisstaube.FetchDirectBeatmapSetAsync(setId) : pisstaube.FetchDirectBeatmapAsync(beatmapId)))); }
public uint GetPosition(SoraDbContext ctx, PlayMode mode) { var pos = mode switch // Prevent position jumping around. { PlayMode.Osu => PerformancePointsOsu <= 0 ? 0 : -1, PlayMode.Taiko => PerformancePointsTaiko <= 0 ? 0 : -1, PlayMode.Ctb => PerformancePointsCtb <= 0 ? 0 : -1, PlayMode.Mania => PerformancePointsMania <= 0 ? 0 : -1, _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), }; if (pos == -1) { pos = mode switch { PlayMode.Osu => ctx.Leaderboard.Count(x => x.PerformancePointsOsu > PerformancePointsOsu), PlayMode.Taiko => ctx.Leaderboard .Count(x => x.PerformancePointsTaiko > PerformancePointsTaiko), PlayMode.Ctb => ctx.Leaderboard.Count(x => x.PerformancePointsCtb > PerformancePointsCtb), PlayMode.Mania => ctx.Leaderboard .Count(x => x.PerformancePointsMania > PerformancePointsMania), _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), } } ;
public static async Task <(bool Pass, DbScore score)> ParseScore(SoraDbContext ctx, string encScore, string iv, string osuVersion) { var decryptedScore = Crypto.DecryptString( Convert.FromBase64String(encScore), Encoding.ASCII.GetBytes(string.Format(PRIVATE_KEY, osuVersion)), Convert.FromBase64String(iv) ); var x = decryptedScore.Split(':'); var score = new DbScore { FileMd5 = x[0], ScoreOwner = await DbUser.GetDbUser(ctx, x[1]), Count300 = int.Parse(x[3]), Count100 = int.Parse(x[4]), Count50 = int.Parse(x[5]), CountGeki = int.Parse(x[6]), CountKatu = int.Parse(x[7]), CountMiss = int.Parse(x[8]), TotalScore = int.Parse(x[9]), MaxCombo = short.Parse(x[10]), Mods = (Mod)uint.Parse(x[13]), PlayMode = (PlayMode)byte.Parse(x[15]), Date = DateTime.Now, }; score.UserId = score.ScoreOwner?.Id ?? 0; return(bool.Parse(x[14]), score); }
public int Position(SoraDbContext ctx) => ctx.Scores.Where(s => s.TotalScore > TotalScore && s.FileMd5 == FileMd5 && s.PlayMode == PlayMode && s.UserId != UserId) .AsParallel() .GroupBy(s => s.UserId).Count() + 1;
public async Task <IActionResult> GetReplay( [FromQuery(Name = "c")] int replayId, [FromQuery(Name = "m")] PlayMode mode, [FromQuery(Name = "u")] string userName, [FromQuery(Name = "h")] string pass, [FromServices] SoraDbContext ctx ) { var user = await DbUser.GetDbUser(ctx, userName); if (user == null) { return(Ok("err: pass")); } if (!user.IsPassword(pass)) { return(Ok("err: pass")); } var s = await DbScore.GetScore(ctx, replayId); if (s == null) { return(NotFound()); } return(File(System.IO.File.OpenRead("data/replays/" + s.ReplayMd5), "binary/octet-stream", s.ReplayMd5)); }
public AchievementController( SoraDbContext ctx, Cache cache ) { _ctx = ctx; _cache = cache; }
public static Task <DbScore> GetLatestScore( SoraDbContext ctx, DbScore newerScore ) => ctx.Scores.Where(x => x.FileMd5 == newerScore.FileMd5 && x.UserId == newerScore.UserId && x.PlayMode == newerScore.PlayMode) .OrderByDescending(x => x.TotalScore) .FirstOrDefaultAsync();
public static async Task InsertScore(SoraDbContext ctx, DbScore score) { var so = score.ScoreOwner; // Fix for an Issue with Inserting. score.ScoreOwner = null; ctx.Add(score); score.ScoreOwner = so; // Restore ScoreOwner await ctx.SaveChangesAsync(); }
/// <summary> /// Create Default Achievements /// </summary> /// <param name="factory">Context Factory</param> public static async Task CreateDefaultAchievements(SoraDbContext ctx) { if (ctx.Achievements.FirstOrDefault(x => x.Name == "oog") == null) { await DbAchievement.NewAchievement( ctx, "oog", "Oooooooooooooooog!", "You just oooged JSE", "https://onii-chan-please.come-inside.me/achivement_oog.png" ); } }
public static async Task NewAchievement(SoraDbContext ctx, string name, string displayName, string desc, string icon) { await ctx.Achievements.AddAsync(new DbAchievement { Name = name, Description = desc, DisplayName = displayName, IconURI = icon, }); await ctx.SaveChangesAsync(); }
public OnLoginRequestEvent(SoraDbContext ctx, Config cfg, PresenceService pcs, ChannelService cs, Cache cache, ILogger <OnLoginRequestEvent> logger) { _ctx = ctx; _cfg = cfg; _pcs = pcs; _cs = cs; _cache = cache; _logger = logger; }
public string ToOsuString(SoraDbContext ctx) => $"{Id}|" + $"{ScoreOwner.UserName.Replace("|", "I")}|" + $"{TotalScore}|" + $"{MaxCombo}|" + $"{Count50}|" + $"{Count100}|" + $"{Count300}|" + $"{CountMiss}|" + $"{CountKatu}|" + $"{CountGeki}|" + $"{MaxCombo >= Count50 + Count100 + Count300 + CountMiss}|" + $"{(short) Mods}|" + $"{UserId}|" + $"{Position(ctx)}|" + $"{(int) Date.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds}|" + $"{Id}";
public IrcClient(TcpClient client, SoraDbContext ctx, IServerConfig cfg, PresenceService ps, ChannelService cs, EventManager evmng, IrcServer parent) { _client = client; _ctx = ctx; _cfg = cfg; _ps = ps; _parent = parent; _cs = cs; _evmng = evmng; }
public WebController( SoraDbContext ctx, EventManager ev, PresenceService ps, Cache cache, Config config, Bot.Sora sora, Pisstaube pisstaube) { _ctx = ctx; _ev = ev; _ps = ps; _cache = cache; _config = config; _sora = sora; _pisstaube = pisstaube; }
public static async IAsyncEnumerable <DbScore> GetScores( SoraDbContext ctx, string fileMd5, DbUser user, PlayMode playMode = PlayMode.Osu, bool friendsOnly = false, bool countryOnly = false, bool modOnly = false, Mod mods = Mod.None, bool onlySelf = false ) { const CountryId cid = CountryId.XX; /* Legacy Code * if (countryOnly) * cid = UserStats.GetUserStats(factory, user.Id).CountryId; */ var query = ctx.Scores .Where(score => score.FileMd5 == fileMd5 && score.PlayMode == playMode) .Where( score => !friendsOnly || ctx.Friends .Where(f => f.UserId == user.Id) .Select(f => f.FriendId) .Contains(score.UserId) ) /* Legacy Code TODO: Implement * .Where( * score * => !countryOnly || factory.Get().UserStats * .Select(c => c.CountryId) * .Contains(cid) * ) */ .Where(score => !modOnly || score.Mods == mods) .Where(score => !onlySelf || score.UserId == user.Id) .OrderByDescending(score => score.TotalScore) .Include(x => x.ScoreOwner) .ToList() .GroupBy(s => s.UserId) // TODO: this is stupid. but we cant change it :c .Select(s => s.First()) .Take(50); foreach (var dbScore in query) { yield return(dbScore); } }
public static async Task <DbLeaderboard> GetLeaderboardAsync(SoraDbContext ctx, int userId) { var result = ctx.Leaderboard.Where(t => t.OwnerId == userId).Select(e => e).AsNoTracking().FirstOrDefault(); if (result != null) { return(result); } var lb = new DbLeaderboard { OwnerId = userId }; await ctx.Leaderboard.AddAsync(lb); await ctx.SaveChangesAsync(); return(lb); }
public IrcServer(IServerConfig cfg, SoraDbContext ctx, PresenceService ps, ChannelService cs, EventManager evmng) { _cfg = cfg; _ctx = ctx; _ps = ps; _cs = cs; _evmng = evmng; if (!IPAddress.TryParse(cfg.Server.Hostname, out var ipAddress)) { ipAddress = Dns.GetHostEntry(cfg.Server.Hostname).AddressList[0]; } _listener = new TcpListener(ipAddress, cfg.Server.IrcPort); _token = new CancellationTokenSource(); _connectedClients = new List <IrcClient>(); _conLocker = new object(); }
public static Task <DboAuthClient> GetClient(SoraDbContext ctx, string id) { var gid = new Guid(id); return(ctx.OAuthClients.FirstOrDefaultAsync(x => x.Id == gid)); }
public OnFriendAddEvent(SoraDbContext ctx) => _ctx = ctx;
public OAuthController(SoraDbContext ctx, Config cfg, ILogger <OAuthController> logger) { _ctx = ctx; _cfg = cfg; _logger = logger; }
public static async Task RemoveFriend(SoraDbContext ctx, int userId, int friendId) { ctx.RemoveRange(ctx.Friends.Where(x => x.UserId == userId && x.FriendId == friendId)); await ctx.SaveChangesAsync(); }
public static async Task AddFriend(SoraDbContext ctx, int userId, int friendId) { await ctx.Friends.AddAsync(new DbFriend { UserId = userId, FriendId = friendId }); await ctx.SaveChangesAsync(); }
public static IEnumerable <int> GetFriends(SoraDbContext ctx, int userId) => ctx .Friends .Where(t => t.UserId == userId) .Select(x => x.FriendId).ToList();
public static DbBeatmap GetBeatmap(SoraDbContext ctx, string fileMd5) => ctx .Beatmaps .FirstOrDefault(t => t.FileMd5 == fileMd5);
public OnSendUserStatusEvent(PresenceService ps, SoraDbContext ctx) { _ps = ps; _ctx = ctx; }
public async Task <IActionResult> PostSubmitModular( [FromServices] PresenceService ps, [FromServices] SoraDbContext ctx, [FromServices] EventManager ev, [FromServices] Pisstaube pisstaube, [FromServices] Bot.Sora sora, [FromServices] Config config ) { 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) = await ScoreSubmissionParser.ParseScore(ctx, encScore, iv, osuver); var dbUser = await DbUser.GetDbUser(ctx, score.ScoreOwner.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! } var set = await pisstaube.FetchBeatmapSetAsync(score.FileMd5); var bm = set?.ChildrenBeatmaps.First(x => x.FileMD5 == score.FileMd5) ?? new Beatmap(); if (!pass || !RankedMods.IsRanked(score.Mods) || !Rankable.HasScoreboard(set?.RankedStatus ?? Pisstaube.RankedStatus.Graveyard)) { 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"); await pisstaube.DownloadBeatmapAsync(score.FileMd5); await using (var m = new MemoryStream()) { replayFileData.CopyTo(m); m.Position = 0; score.ReplayMd5 = Hex.ToHex(Crypto.GetMd5(m)) ?? string.Empty; if (!string.IsNullOrEmpty(score.ReplayMd5)) { await using var replayFile = System.IO.File.Create($"data/replays/{score.ReplayMd5}"); m.Position = 0; m.WriteTo(replayFile); m.Close(); replayFile.Close(); } } score.PerformancePoints = score.ComputePerformancePoints(); var oldScore = await DbScore.GetLatestScore(ctx, score); var oldLb = await DbLeaderboard.GetLeaderboardAsync(ctx, score.ScoreOwner); var oldStdPos = oldLb.GetPosition(ctx, score.PlayMode); var oldAcc = oldLb.GetAccuracy(ctx, score.PlayMode); double newAcc; if (oldScore != null && oldScore.TotalScore <= score.TotalScore) { ctx.Remove(oldScore); System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}"); await DbScore.InsertScore(ctx, score); } else if (oldScore == null) { await DbScore.InsertScore(ctx, score); } else { System.IO.File.Delete($"data/replays/{oldScore.ReplayMd5}"); } var newlb = await DbLeaderboard.GetLeaderboardAsync(ctx, score.ScoreOwner); newlb.IncreasePlaycount(score.PlayMode); newlb.IncreaseScore((ulong)score.TotalScore, true, score.PlayMode); newlb.IncreaseScore((ulong)score.TotalScore, false, score.PlayMode); newlb.UpdatePp(ctx, score.PlayMode); await newlb.SaveChanges(ctx); var newStdPos = newlb.GetPosition(ctx, score.PlayMode); newAcc = newlb.GetAccuracy(ctx, score.PlayMode); var newScore = await DbScore.GetLatestScore(ctx, score); ulong oldRankedScore; ulong newRankedScore; double oldPp; double newPp; switch (score.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?.Position(ctx) ?? 0; var oldScorePosition = oldScore?.Position(ctx) ?? 0; if (newScorePosition == 1) { sora.SendMessage( $"[http://{config.Server.ScreenShotHostname}/{score.ScoreOwner.Id} {score.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}{score.ScoreOwner.UserName}", $"{LCol.PURPLE}( {score.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, score.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 SignUp(SoraDbContext context, IServerConfig serverConfig) { _context = context; _serverConfig = serverConfig; }