public bool LoadPlugin(IApplicationBuilder app, string filename, bool isDep = false) { try { using var strm = File.OpenRead(filename); // Load from stream instead, allow us to live reload. var asm = _context.LoadFromStream(strm); if (asm == null) { return(false); } _loadedPlugins.Add(filename, asm); _ev.LoadAssembly(asm); _logger.LogInformation("Loaded new Assembly {asm}", asm); // Register ASP.NET Core Controllers _appPartManager.ApplicationParts.Add(new AssemblyPart(asm)); if (!isDep) { GetEntryPoint(asm)?.OnEnable(app); } return(true); } catch (Exception ex) { Logger.Err(ex); return(false); } }
public bool UnloadPlugins() { try { _context.Unload(); return(true); } catch (Exception ex) { Logger.Err(ex); return(false); } }
public void OnBanchoMatchStart(BanchoMatchStartArgs args) { if (args.Pr.ActiveMatch == null || args.Pr.ActiveMatch.HostId != args.Pr.User.Id) { return; } Logger.Info( "%#FFFFFF% a %#f1fc5a%Multiplayer Room %#FFFFFF%called %#F94848%" + args.Pr.ActiveMatch.Name, "%#B342F4%(", args.Pr.ActiveMatch.MatchId, "%#B342F4%) %#FFFFFF%has started their Match!" ); args.Pr.ActiveMatch.Start(); args.Pr.ActiveMatch.Update(); }
public async Task<IActionResult> GetBeatmap( string map, [FromServices] Pisstaube pisstaube) { Logger.Debug(map); if (!Directory.Exists("data/beatmaps")) Directory.CreateDirectory("data/beatmaps"); var beatmap = await pisstaube.DownloadBeatmapAsync(map, false); // No config reading for you :3 map = map.Replace("..", string.Empty); if (!System.IO.File.Exists(beatmap)) return NotFound($"Could not find Beatmap with the Name of {map}"); return File(System.IO.File.OpenRead(beatmap), "text/html"); }
public async void StartAsync() { await Task.Run( () => { _listener.Start(); var isCanceled = false; _token.Token.Register( () => isCanceled = true ); while (!isCanceled) { try { var client = _listener.AcceptTcpClient(); var ircClient = new IrcClient(client, _ctx, _cfg, _ps, _cs, _evmng, this); lock (_conLocker) { _connectedClients.Add(ircClient); } new Thread(ircClient.Start).Start(); } catch (Exception ex) { Logger.Err(ex); } } lock (_conLocker) { foreach (var c in _connectedClients) { c.Stop(); } } } ); }
public Task RunAsync() { BotPresence = new Presence { Status = new UserStatus { Status = Status.Watching, Playmode = PlayMode.Osu, BeatmapChecksum = "nothing", BeatmapId = 0, StatusText = "over you!", CurrentMods = Mod.TouchDevice, }, Info = new UserInformation { Latitude = 0, Longitude = 0, ClientPermission = LoginPermissions.User | LoginPermissions.Administrator | LoginPermissions.Moderator | LoginPermissions.Supporter | LoginPermissions.TorneyStaff | LoginPermissions.BAT, CountryId = CountryId.XX, TimeZone = 0, }, ["BOT"] = true, ["IRC"] = true, User = _dbUser, }; _ps.Push(new PresenceSingle(BotPresence.User.Id)); _ps.Join(BotPresence); Logger.Info("Hey, I'm Sora! I'm a bot and i say Hello World!"); return(Task.CompletedTask); }
public IPlugin GetEntryPoint(Assembly asm) { if (_entryPoints.ContainsKey(asm)) { return(_entryPoints[asm]); } var iplug = asm.GetTypes() .FirstOrDefault( x => x.IsClass && (x.BaseType == typeof(IPlugin) || x.BaseType == typeof(Plugin)) ); if (iplug == null) { Logger.Warn("No entry point found for plugin", asm); _entryPoints.Add(asm, null); return(null); } var tArgs = (from cInfo in iplug.GetConstructors() from pInfo in cInfo.GetParameters() select _ev.Provider.GetService(pInfo.ParameterType)).ToArray(); if (tArgs.Any(x => x == null)) { throw new Exception("Could not find Dependency, are you sure you registered the Dependency?"); } var retVal = Activator.CreateInstance(iplug, tArgs) as IPlugin; _entryPoints.Add(asm, retVal); return(retVal); }
public void OnBroadcastFrames(BanchoMatchChangeSettingsArgs args) { if (args.Pr.ActiveMatch == null) { return; } if (args.Pr.ActiveMatch.HostId != args.Pr.User.Id) { return; } if (args.Pr.ActiveMatch.Name != args.Room.Name) { Logger.Info( "%#F94848%" + args.Pr.User.UserName, "%#B342F4%(", args.Pr.User.Id, "%#B342F4%)", "%#FFFFFF% renamed a %#f1fc5a%Multiplayer Room %#FFFFFF%called %#F94848%" + args.Pr.ActiveMatch.Name, "%#B342F4%(", args.Room.MatchId, "%#B342F4%)", "%#FFFFFF%and is now called %#F94848%" + args.Room.Name, "%#B342F4%(", args.Room.MatchId, "%#B342F4%)" ); } Logger.Info( "%#F94848%" + args.Pr.User.UserName, "%#B342F4%(", args.Pr.User.Id, "%#B342F4%)", "%#FFFFFF%changed the Settings of a %#f1fc5a%Multiplayer Room %#FFFFFF%called %#F94848%" + args.Room.Name, "%#B342F4%(", args.Room.MatchId, "%#B342F4%)" ); args.Pr.ActiveMatch.ChangeSettings(args.Room); args.Pr.ActiveMatch.Update(); }
public async Task <IActionResult> IndexPost([FromHeader(Name = "osu-token")] string clientToken = null) { try { Response.Headers["cho-protocol"] = "19"; Response.Headers["Connection"] = "keep-alive"; Response.Headers["Keep-Alive"] = "timeout=60, max=100"; Response.Headers["cho-server"] = "Sora (https://github.com/Mempler/Sora)"; Response.StatusCode = 200; await using var body = new MemoryStream(); await Request.Body.CopyToAsync(body); body.Position = 0; await using var mw = MStreamWriter.New(); using var mr = new MStreamReader(body); var pr = new Presence(); if (string.IsNullOrEmpty(clientToken)) { Response.Headers["cho-token"] = pr.Token.ToString(); string ip = Request.Headers["X-Real-IP"]; if (string.IsNullOrEmpty(ip)) { ip = "127.0.0.1"; } await _evManager.RunEvent(EventType.BanchoLoginRequest, new BanchoLoginRequestArgs { Reader = mr, Writer = mw, Pr = pr, IpAddress = ip, }); mw.Flush(); return(await RetOut(mw.BaseStream)); } if (_presenceService.TryGet(new Token(clientToken.Trim()), out pr)) { while (true) { try { pr["LAST_PONG"] = DateTime.Now; if (Request.ContentLength - body.Position < 7) { break; // Dont handle any invalid packets! (less then bytelength of 7) } var packetId = (PacketId)mr.ReadInt16(); mr.ReadBoolean(); var packetData = mr.ReadBytes(); await using var packetDataStream = new MemoryStream(packetData); using var packetDataReader = new MStreamReader(packetDataStream); await _evManager.RunEvent( EventType.BanchoPacket, new BanchoPacketArgs { Pr = pr, PacketId = packetId, Data = packetDataReader } ); } catch (Exception ex) { Logger.Err(ex); break; } } try { await using var m = new MemoryStream(); if (Response.Body.CanWrite) { pr.WritePackets(m); } return(await RetOut(m)); } catch (Exception ex) { Logger.Err(ex); // Ignored because it may throw an exception. } } else { return(StatusCode(403)); } } catch (Exception ex) { Logger.Err(ex); } return(Ok()); }
private static void OnProcessExit(object sender, System.EventArgs e) { Logger.Info("Killing everything.."); host?.Dispose(); // This is stupid. using statement ain't working... Environment.Exit(0); // we also have to call it manually ... }
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); } }
public async Task <IActionResult> GetScoreResult( [FromQuery(Name = "v")] ScoreboardType type, [FromQuery(Name = "c")] string fileMd5, [FromQuery(Name = "f")] string f, [FromQuery(Name = "m")] PlayMode playMode, [FromQuery(Name = "i")] int i, [FromQuery(Name = "mods")] Mod mods, [FromQuery(Name = "us")] string us, [FromQuery(Name = "ha")] string pa, [FromServices] IServiceProvider serviceProvider, [FromServices] SoraDbContext ctx, [FromServices] DbContextPool <SoraDbContext> ctxPool, [FromServices] Pisstaube pisstaube, [FromServices] Cache cache) { try { var dbUser = await DbUser.GetDbUser(ctx, us); if (dbUser?.IsPassword(pa) != true) { return(Ok("error: pass")); } var cacheHash = Hex.ToHex( Crypto.GetMd5( $"{fileMd5}{playMode}{mods}{type}{dbUser.Id}{dbUser.UserName}" ) ); if (cache.TryGet($"sora:Scoreboards:{cacheHash}", out string cachedData)) { return(Ok(cachedData)); } var scores = DbScore.GetScores(ctx, fileMd5, dbUser, playMode, type == ScoreboardType.Friends, type == ScoreboardType.Country, type == ScoreboardType.Mods, mods); BeatmapSet set = null; DbScore ownScore = null; var beatmap = DbBeatmap.GetBeatmap(ctx, fileMd5); if (beatmap == null) { var apiSet = await pisstaube.FetchBeatmapSetAsync(fileMd5); if (apiSet == null) { goto JustContinue; } var beatmaps = DbBeatmap.FromBeatmapSet(apiSet).ToList(); var beatmapChecksums = beatmaps.Select(s => s.FileMd5); var dbBeatmaps = ctx.Beatmaps.Where(rset => beatmapChecksums.Any(lFileMd5 => rset.FileMd5 == lFileMd5)) .ToList(); var pool = serviceProvider.GetRequiredService <DbContextPool <SoraDbContext> >(); Task.WaitAll(beatmaps.Select(rawBeatmap => Task.Run(async() => { var context = pool.Rent(); try { var dbBeatmap = dbBeatmaps.FirstOrDefault(s => s.FileMd5 == rawBeatmap.FileMd5); if (dbBeatmap != null && (dbBeatmap.Flags & DbBeatmapFlags.RankedFreeze) != 0) { rawBeatmap.RankedStatus = dbBeatmap.RankedStatus; rawBeatmap.Flags = dbBeatmap.Flags; } context.Beatmaps.AddOrUpdate(rawBeatmap); await context.SaveChangesAsync(); } finally { pool.Return(context); } })).ToArray()); beatmap = beatmaps.FirstOrDefault(s => s.FileMd5 == fileMd5); } await foreach (var score in DbScore.GetScores(ctx, fileMd5, dbUser, playMode, false, false, false, mods, true)) { ownScore = score; break; } if (beatmap != null) { set = new BeatmapSet { SetID = beatmap.Id, Artist = beatmap.Artist, Title = beatmap.Title, RankedStatus = beatmap.RankedStatus, ChildrenBeatmaps = new List <Beatmap> { new Beatmap { FileMD5 = beatmap.FileMd5, DiffName = beatmap.DiffName, ParentSetID = beatmap.SetId, BeatmapID = beatmap.Id, Mode = beatmap.PlayMode, }, }, } } ; JustContinue: var sboard = new Scoreboard(set?.ChildrenBeatmaps.FirstOrDefault(bm => bm.FileMD5 == fileMd5), set, scores, ownScore); cache.Set($"sora:Scoreboards:{cacheHash}", cachedData = await sboard.ToOsuString(ctxPool), TimeSpan.FromSeconds(30)); return(Ok(cachedData)); } catch (Exception ex) { Logger.Err(ex); return(Ok("Failed")); } }
public ConsoleCommandService(SoraDbContext ctx) { Commands = new List <ConsoleCommand>(); _mut = new object(); #region DefaultCommands RegisterCommand( "help", "Get a list of ALL Commands!", new List <Argument> { new Argument { ArgName = "command" } }, 0, args => { var l = "\n====== Command List ======\n"; foreach (var cmd in Commands) { var aList = "\t<"; var i = 0; foreach (var a in cmd.Args) { aList += a.ArgName; if (i >= cmd.ExpectedArgs) { aList += "?"; } aList += ", "; i++; } aList = aList.TrimEnd(cmd.Args.Count < 1 ? '<' : ' ').TrimEnd(','); if (cmd.Args.Count > 0) { aList += ">"; } l += "\n%#1c9624%/*\n"; l += cmd.Description; l += $"\n*/{LCol.WHITE}\n"; l += "\n" + cmd.Command + aList; l += "\n"; } l += "\n=========================="; Logger.Info(l); return(true); } ); RegisterCommand( "clear", "Clear Console", new List <Argument>(), 0, args => { Console.Clear(); return(true); } ); RegisterCommand( "adduser", "Add a User to our Database", new List <Argument> { new Argument { ArgName = "Username" }, new Argument { ArgName = "Password" }, new Argument { ArgName = "E-Mail" }, new Argument { ArgName = "Permissions" }, }, 3, args => { var u = DbUser.RegisterUser(ctx, Permission.From(args[3..].Join()), args[0], args[2], args[1], false).Result; if (u == null) { Logger.Err("Failed! User has already been registered!"); return(true); } Logger.Info(args[1]); Logger.Info( "Created User", "%#F94848%" + u.UserName, "%#B342F4%(", u.Id, "%#B342F4%)" ); return(true); }
public async Task Receive() { var stream = _client.GetStream(); var bytes = new byte[4096]; _writer = new StreamWriter(stream); // TODO: Finish http://www.networksorcery.com/enp/protocol/irc.htm try { int i; while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) { if (_exit) { return; } var data = Encoding.UTF8.GetString(bytes, 0, i).Split("\n"); foreach (var cmd in data.Select(d => d.Split(" ")) .Where(cmd => !string.IsNullOrEmpty(cmd[0])) .Where(cmd => !string.IsNullOrWhiteSpace(cmd[0]))) { switch (cmd[0]) { case "USER": if (_authorized) { SendCodeMessage(462, "Unauthorized command (already authorized!)"); continue; } if (cmd.Length < 2) { SendCodeMessage(451, "You have not registered"); continue; } _nickname = cmd[1].Trim(); var rUser = DbUser.GetDbUser(_ctx, cmd[1].Trim()).Result; if (rUser == null) { SendCodeMessage(451, "You have not registered"); continue; } _user = rUser; if (_authorized) { SendCodeMessage(462, "Unauthorized command (already authorized!)"); continue; } if (rUser?.IsPassword(Hex.ToHex(Crypto.GetMd5(_pass.Trim()))) != true) { if (string.IsNullOrEmpty(_nickname)) { _nickname = "anonymous"; } Logger.Info(_pass); SendCodeMessage(464, "Password incorrect"); continue; } _presence = new Presence(); _presence.User = _user; _presence["STATUS"] = new UserStatus(); _presence["IRC"] = true; WriteConnectionResponse(); WriteStatus(); WriteMotd(); _authorized = true; break; case "JOIN": if (_presence == null || !_authorized) { SendCodeMessage(444, "You're not logged in"); break; } if (_cs.TryGet(cmd[1].Trim(), out var channel)) { SendCodeMessage(403, $"{cmd[1]}: No such Channel!"); break; } channel.Join(_presence); /* * if (!) * { * SendCodeMessage(482, "You're not allowed to Join this Channel!"); * break; * } */ if (channel.Topic == "") { SendCodeMessage(331, "No topic is set", channel: channel.Name); } else { SendCodeMessage(332, channel.Topic, channel: channel.Name); } var uList = string.Join( " ", channel.Presences .Select( ps => { var ret = ps.User.UserName.Replace(" ", "_"); if (ps.User.Permissions.HasPermission(Permission.GROUP_CHAT_MOD)) { ret = "@" + ret; } else if (ps.User.Permissions.HasPermission( Permission.GROUP_DONATOR )) { ret = "+" + ret; } return(ret); }) .ToArray() ); uList += " @olSora"; SendCodeMessage(353, $"{uList}", channel: "= " + channel.Name); SendCodeMessage(366, "End of NAMES list", channel: channel.Name); break; case "PING": if (_presence == null || !_authorized) { SendCodeMessage(444, "You're not logged in"); break; } await _evmng.RunEvent(EventType.BanchoPong, new BanchoPongArgs { Pr = _presence }); SendMessage($"PONG {_cfg.Server.Hostname}: {cmd[1]}"); break; case "PASS": _pass = cmd[1]; break; case "QUIT": _client.Close(); _parent.RemoveTcpClient(this); return; // Ignored Commands case "NICK": case "CAP": break; default: Logger.Debug(string.Join(" ", cmd)); if (!_authorized) { SendCodeMessage(444, "You're not logged in"); } break; } } _writer.Flush(); } } catch (Exception e) { Logger.Err(e); _client.Close(); } }