예제 #1
0
        public async Task Leave(Presence user)
        {
            user.Match = null;
            await Channel.RemoveUser(user);

            if (Channel.Users.IsEmpty)
            {
                Global.Channels.Remove(Channel.TrueName);
                Global.Rooms.Remove(Id);
                await Global.OnlineManager.AddPacketToAllUsers(await FastPackets.DisposeMatch(Id));

                XConsole.Log($"Match {ToString()} ended", ConsoleColor.Green);
            }
            else
            {
                var slot = GetSlot(user.Id);

                if (slot is null)
                {
                    return;
                }

                slot.User   = null;
                slot.Mods   = Mods.NoMod;
                slot.Team   = MatchTeam.Neutral;
                slot.Status = SlotStatus.Open;

                if (user.Id == HostId)
                {
                    Host = Slots.First(x => (x.Status & SlotStatus.HasPlayer) != 0).User;
                }

                await Update();
            }
        }
예제 #2
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            var message = reader.ReadBanchoObject <BanchoMessage>();

            if (message.To == Global.Bot.Name)
            {
                if (message.Body.StartsWith(Global.Config.CommandPrefix))
                {
                    await CommandHandler.Process(message.Body.Substring(Global.Config.CommandPrefix.Length), user);
                }
                return;
            }

            var location = Global.OnlineManager.GetByName(message.To);

            if (location is null)
            {
                await user.Notify("Пользователь не в сети.");

                return;
            }

            await location.SendMessage(message.Body, user);

            if (message.Body.StartsWith(Global.Config.CommandPrefix))
            {
                await CommandHandler.Process(message.Body.Substring(Global.Config.CommandPrefix.Length), user);
            }

            XConsole.Log($"{user} -> {location}: {message.Body}");
        }
예제 #3
0
        public static async Task Handle(PacketReader _, Presence user)
        {
            user.InLobby = false;
            await Global.Channels["#lobby"].RemoveUser(user);

            XConsole.Log($"{user} left from lobby", ConsoleColor.Cyan);
        }
예제 #4
0
        public static async Task Handle(PacketReader _, Presence user)
        {
            if (user.Match is null)
            {
                return;
            }

            await user.Match.Leave(user);

            XConsole.Log($"{user} left from multiplayer room {user.Match}", ConsoleColor.Cyan);
        }
예제 #5
0
        public static async Task Handle(PacketReader _, Presence user)
        {
            user.InLobby = true;
            await Global.Channels["#lobby"].JoinUser(user);

            foreach (var(_, match) in Global.Rooms)
            {
                user.WaitingPackets.Enqueue(await FastPackets.NewMatch(match.Foreign()));
            }

            XConsole.Log($"{user} joined to lobby", ConsoleColor.Cyan);
        }
예제 #6
0
        //TODO: /web/

        public async Task <Presence> GetPresence()
        {
            var user  = Auth.GetSafeName(Request.Query["u"]);
            var pwMd5 = (string)Request.Query["h"];

            var presence = await Auth.Login(user, pwMd5);

            if (presence is null || !presence.Online)
            {
                XConsole.Log($"{presence?.ToString() ?? user} requested {Request.Path} while not online", ConsoleColor.Yellow);
            }

            return(presence);
        }
예제 #7
0
        public static async Task Handle(PacketReader _, Presence user)
        {
            var toSpec = user.Spectating;

            if (toSpec is null)
            {
                XConsole.Log($"{user} failed to stop spectating (not spectating)", ConsoleColor.Yellow);
                return;
            }

            await toSpec.RemoveSpectator(user);

            XConsole.Log($"{user} stop spectating {toSpec}", ConsoleColor.Magenta);
        }
예제 #8
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            var id     = reader.ReadInt32();
            var toSpec = Global.OnlineManager.GetById(id);

            if (toSpec is null)
            {
                XConsole.Log($"{user} failed to spectate <({id})> (offline)", ConsoleColor.Yellow);
                return;
            }

            await toSpec.AddSpectator(user);

            XConsole.Log($"{user} started spectating {toSpec}", ConsoleColor.Magenta);
        }
예제 #9
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            var channel = reader.ReadString();

            if (!Global.Channels.ContainsKey(channel) || channel == "#lobby")
            {
                return;
            }

            var c = Global.Channels[channel];

            await c.RemoveUser(user);

            XConsole.Log($"{user} left from {channel}", ConsoleColor.Cyan);
        }
예제 #10
0
        public static async Task Handle(PacketReader _, Presence user)
        {
            var toSpec = user.Spectating;

            if (toSpec is null)
            {
                XConsole.Log($"{user} sent cant spectate while not spectatinmg", ConsoleColor.Yellow);
                return;
            }

            var packet = await FastPackets.CantSpectate(user.Id);

            toSpec.WaitingPackets.Enqueue(packet);
            await toSpec.AddPacketToSpectators(packet);
        }
예제 #11
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            if (user.Match is not null)
            {
                await user.Match.Leave(user);
            }

            var match = reader.ReadBanchoObject <Match>();

            Global.Rooms[match.Id] = match;

            await match.Join(user, match.Password);

            await match.Update();

            await Global.OnlineManager.AddPacketToAllUsers(await FastPackets.NewMatch(match.Foreign()));

            XConsole.Log($"{user} created multiplayer room {match}", ConsoleColor.Green);
        }
예제 #12
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            user.LastPong = 0;

            foreach (var(_, c) in Global.Channels)
            {
                await c.RemoveUser(user);
            }

            if (user.Match is not null)
            {
                await user.Match.Leave(user);
            }

            await Global.OnlineManager.Remove(user);

            await Global.OnlineManager.AddPacketToAllUsers(await FastPackets.Logout(user.Id));

            XConsole.Log($"{user} logged out", ConsoleColor.Green);
        }
예제 #13
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            var channel = reader.ReadString();

            if (!Global.Channels.ContainsKey(channel) || channel == "#lobby")
            {
                return;
            }

            var c = Global.Channels[channel];

            if (c.IsLobby && !user.InLobby)
            {
                return;
            }

            await c.JoinUser(user);

            XConsole.Log($"{user} joined {c}", ConsoleColor.Cyan);
        }
예제 #14
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            var message = reader.ReadBanchoObject <BanchoMessage>();

            if (!user.JoinedChannels.ContainsKey(message.To))
            {
                await user.Notify("Вы не находитесь в данном канале!");

                return;
            }

            var channel = user.JoinedChannels[message.To];

            await channel.WriteMessage(message.Body, user);

            if (message.Body.StartsWith(Global.Config.CommandPrefix))
            {
                await CommandHandler.Process(message.Body.Substring(Global.Config.CommandPrefix.Length), user, channel);
            }

            XConsole.Log($"{user} -> {message.To}: {message.Body}");
        }
예제 #15
0
        public static async Task Handle(PacketReader reader, Presence user)
        {
            if (user.Match is not null)
            {
                await user.Match.Leave(user);
            }

            var id = reader.ReadInt32();

            if (!Global.Rooms.ContainsKey(id))
            {
                user.WaitingPackets.Enqueue(FastPackets.MatchJoinFail);
                return;
            }

            var password = reader.ReadString();
            var match    = Global.Rooms[id];

            await match.Join(user, password);

            XConsole.Log($"{user} joined to multiplayer room {match}", ConsoleColor.Cyan);
        }
예제 #16
0
        public async Task <IActionResult> Bancho(
            [FromHeader(Name = "osu-token")] string token,
            [FromHeader(Name = "User-Agent")] string userAgent
            )
        {
            if (Request.Method == "GET" || userAgent != "osu!")
            {
                return(Default());
            }

            Response.Headers["cho-protocol"] = Misc.BanchoProtocolVersion.ToString();

            await using var ms = new MemoryStream();
            await Request.Body.CopyToAsync(ms);

            ms.Position = 0;

            if (string.IsNullOrEmpty(token))
            {
                var sw = Stopwatch.StartNew();

                var req = Encoding.UTF8.GetString(ms.ToArray()).Split(new[] { "\n", "\r\n" }, StringSplitOptions.None);

                if (req.Length != 4)
                {
                    return(NotFound());
                }

                Response.Headers["cho-token"] = "chikatto::no-token";

                var u = await Auth.Login(req[0], req[1]);

                var clientData = req[2].Split(":");

                if (u is null)
                {
                    return(SendPackets(new[]
                    {
                        await FastPackets.UserId(-1) // bad password
                    }));
                }

                if (u.LastPong > new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds() - 10)
                {
                    return(SendPackets(new[]
                    {
                        await FastPackets.UserId(-1), // bad password
                        await FastPackets.Notification("User already logged in")
                    }));
                }

                u.LastPong = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();

                if (u.Spectating is not null)
                {
                    await u.Spectating.RemoveSpectator(u);
                }

                if (u.Match is not null)
                {
                    await u.Match.Leave(u);
                }

                foreach (var(_, us) in u.Spectators)
                {
                    await u.RemoveSpectator(us);
                }

                var packets = new List <Packet>
                {
                    await FastPackets.ProtocolVersion(),
                    await FastPackets.UserId(u.Id),
                    await FastPackets.MainMenuIcon(Global.Config.LogoIngame, Global.Config.LogoClickUrl),
                    await FastPackets.Notification($"Welcome back!\r\nChikatto Build v{Misc.Version}"),
                    await FastPackets.BanchoPrivileges(await u.GetBanchoPermissions() | BanchoPermissions.Supporter),
                    await FastPackets.FriendList(u.Friends.Select(x => x.Key).ToList()),
                    await FastPackets.BotPresence(),
                };

                if (u.Restricted)
                {
                    if ((u.User.Privileges & Privileges.Restricted) != 0) // account restricted
                    {
                        packets.Add(FastPackets.AccountRestricted);
                        await u.Notify("Your account is currently in restricted mode");
                    }
                    else // account banned
                    {
                        return(SendPackets(new[]
                        {
                            await FastPackets.UserId(-3) // ban client
                        }));
                    }
                }
                else if ((u.User.Privileges & Privileges.Verified) == 0) // user just registered
                {
                    u.User.Privileges |= Privileges.Verified;
                    await Db.Execute("UPDATE users SET priv = @priv WHERE id = @id", new { priv = u.User.Privileges, id = u.User.Id });

                    await u.SendMessage(
                        $"Welcome to our server. \r\nType {Global.Config.CommandPrefix}help to see list of available commands.",
                        Global.Bot);
                }

                if (u.User.Country.ToLower() == "xx")
                {
                    var ip = (string)Request.Headers["X-Real-IP"];
                    u.User.Country = await IpApi.FetchLocation(ip);

                    u.CountryCode = Misc.CountryCodes.ContainsKey(u.User.Country.ToUpper())
                        ? Misc.CountryCodes[u.User.Country.ToUpper()]
                        : (byte)0;
                }

                token = Auth.CreateBanchoToken(u.Id, clientData);
                Response.Headers["cho-token"] = token;

                u.Token  = token;
                u.Online = true;
                await Global.OnlineManager.AddUser(u);

                var users = await Global.OnlineManager.GetOnlineUsers();

                foreach (var us in users)
                {
                    packets.Add(await FastPackets.UserPresence(us));
                }

                var channels = Global.Channels.Select(x => x.Value).Where(x => (x.Read & u.User.Privileges) != 0);

                foreach (var channel in channels)
                {
                    if ((channel.Read & u.User.Privileges) != channel.Read || channel.IsTemp || channel.IsLobby)
                    {
                        continue;
                    }

                    if (channel.Default)
                    {
                        await channel.JoinUser(u);
                    }
                    else
                    {
                        u.WaitingPackets.Enqueue(await channel.GetInfoPacket());
                    }
                }

                packets.Add(FastPackets.ChannelInfoEnd);

                XConsole.Log($"{u} logged in (login took {sw.Elapsed.TotalMilliseconds}ms)", ConsoleColor.Green);

                return(SendPackets(packets));
            }

            if (!token.StartsWith("chikatto:"))
            {
                return(Default());
            }

            var user = Global.OnlineManager.GetByToken(token);

            if (user is null)
            {
                return(SendPackets(new[]
                {
                    await FastPackets.Notification("Server has restarted"),
                    await FastPackets.ServerRestart(0)
                }));
            }

            user.LastPong = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();

            var osuPackets = Packets.GetPackets(ms.ToArray());

            foreach (var packet in osuPackets)
            {
                await packet.Handle(user);
            }

            var res = new List <Packet>();

            while (!user.WaitingPackets.IsEmpty)
            {
                if (user.WaitingPackets.TryDequeue(out var packet))
                {
                    res.Add(packet);
                }
            }

            return(SendPackets(res));
        }