public bool DispatchCommand(CommandContext ctx) { string channelName = ctx.Args.ElementAtOrDefault(1); // no error, apparently if (string.IsNullOrWhiteSpace(channelName)) { return(false); } Channels.GetChannelByName(channelName, channel => { // the original server sends ForceChannel before sending the error message, but this order probably makes more sense. // NEW: REVERT THIS ^^^^ WHEN CONVERTING BACK TO NOT EXCEPTIONS // EXCEPTIONS ARE HEAVY, DON'T USE THEM FOR USER ERRORS YOU IDIOT if (channel == null) { Sessions.SwitchChannel(ctx.Session); throw new ChannelNotFoundCommandException(channelName); } ChannelUsers.HasUser(channel, ctx.User, hasUser => { if (hasUser) { Sessions.SwitchChannel(ctx.Session); throw new AlreadyInChannelCommandException(channel); } string password = string.Join(' ', ctx.Args.Skip(2)); if (!ctx.User.Can(UserPermissions.JoinAnyChannel) && channel.OwnerId != ctx.User.UserId) { if (channel.MinimumRank > ctx.User.Rank) { Sessions.SwitchChannel(ctx.Session); throw new ChannelRankCommandException(channel); } // add capacity check Channels.VerifyPassword(channel, password, success => { if (!success) { Sessions.SwitchChannel(ctx.Session); throw new ChannelPasswordCommandException(channel); } ChannelUsers.JoinChannel(channel, ctx.Session); }); } else { ChannelUsers.JoinChannel(channel, ctx.Session); } }); }); return(true); }
public bool DispatchCommand(CommandContext ctx) { if (!ctx.User.Can(UserPermissions.CreateChannel)) { throw new CommandNotAllowedException(NAME); } bool hasRank; if (ctx.Args.Count() < 2 || (hasRank = ctx.Args.ElementAtOrDefault(1)?.All(char.IsDigit) == true && ctx.Args.Count() < 3)) { throw new CommandFormatException(); } int rank = 0; if (hasRank && !int.TryParse(ctx.Args.ElementAtOrDefault(1), out rank) && rank < 0) { rank = 0; } if (rank > ctx.User.Rank) { throw new InsufficientRankForChangeCommandException(); } string createChanName = string.Join('_', ctx.Args.Skip(hasRank ? 2 : 1)); IChannel createChan; try { createChan = Channels.Create( ctx.User, createChanName, null, !ctx.User.Can(UserPermissions.SetChannelPermanent), rank ); } catch (ChannelExistException) { throw new ChannelExistsCommandException(createChanName); } catch (ChannelInvalidNameException) { throw new ChannelNameInvalidCommandException(); } ChannelUsers.JoinChannel(createChan, ctx.Session); ctx.Connection.SendPacket(new ChannelCreateResponsePacket(Sender, createChan)); return(true); }
public bool DispatchCommand(ICommandContext ctx) { string channelName = ctx.Args.ElementAtOrDefault(1); // no error, apparently if (string.IsNullOrWhiteSpace(channelName)) { return(false); } IChannel channel = Channels.GetChannel(channelName); // the original server sends ForceChannel before sending the error message, but this order probably makes more sense. if (channel == null) { Sessions.SwitchChannel(ctx.Session); throw new ChannelNotFoundCommandException(channelName); } if (ChannelUsers.HasUser(channel, ctx.User)) { Sessions.SwitchChannel(ctx.Session); throw new AlreadyInChannelCommandException(channel); } string password = string.Join(' ', ctx.Args.Skip(2)); if (!ctx.User.Can(UserPermissions.JoinAnyChannel) && channel.Owner != ctx.User) { if (channel.MinimumRank > ctx.User.Rank) { Sessions.SwitchChannel(ctx.Session); throw new ChannelRankCommandException(channel); } if (channel.VerifyPassword(password)) { Sessions.SwitchChannel(ctx.Session); throw new ChannelPasswordCommandException(channel); } } ChannelUsers.JoinChannel(channel, ctx.Session); return(true); }
public void HandlePacket(PacketHandlerContext ctx) { if (ctx.HasSession) { return; } if (!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || userId < 1) { return; } string token = ctx.Args.ElementAtOrDefault(2); if (string.IsNullOrEmpty(token)) { return; } Action <Exception> exceptionHandler = new Action <Exception>(ex => { Logger.Debug($@"[{ctx.Connection}] Auth fail: {ex.Message}"); ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.AuthInvalid)); ctx.Connection.Close(); }); DataProvider.UserAuthClient.AttemptAuth( new UserAuthRequest(userId, token, ctx.Connection.RemoteAddress), res => { DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => { if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now) { ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.Banned, ban)); ctx.Connection.Close(); return; } Users.Connect(res, user => { Sessions.HasAvailableSessions(user, available => { if (!available) { ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.MaxSessions)); ctx.Connection.Close(); return; } Sessions.Create(ctx.Connection, user, session => { string welcome = Server.WelcomeMessage; if (!string.IsNullOrWhiteSpace(welcome)) { ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, welcome.Replace(@"{username}", user.UserName))); } if (WelcomeMessage.HasRandom) { string line = WelcomeMessage.GetRandomString(); if (!string.IsNullOrWhiteSpace(line)) { ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, line)); } } Channels.GetDefaultChannels(channels => { if (!channels.Any()) { return; // what do, this is impossible } // other channels should be joined if MCHAN has been received IChannel firstChan = channels.FirstOrDefault(); ctx.Connection.LastChannel = firstChan; ctx.Connection.SendPacket(new AuthSuccessPacket(user, firstChan, session, Messages.TextMaxLength)); Channels.GetChannels(user.Rank, c => ctx.Connection.SendPacket(new ContextChannelsPacket(c))); ChannelUsers.JoinChannel(firstChan, ctx.Session); }); }); }); }); }, exceptionHandler); }, exceptionHandler ); }
public void HandlePacket(IPacketHandlerContext ctx) { if (ctx.HasSession) { return; } if (!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || userId < 1) { return; } string token = ctx.Args.ElementAtOrDefault(2); if (string.IsNullOrEmpty(token)) { return; } Action <Exception> exceptionHandler = new Action <Exception>(ex => { Logger.Debug($@"<{ctx.Connection.RemoteAddress}> Auth fail: {ex.Message}"); ctx.Connection.Send(new AuthFailPacket(AuthFailReason.AuthInvalid)); ctx.Connection.Close(); }); DataProvider.UserAuthClient.AttemptAuth( new UserAuthRequest(userId, token, ctx.Connection.RemoteAddress), res => { DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => { if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now) { ctx.Connection.Send(new AuthFailPacket(AuthFailReason.Banned, ban)); ctx.Connection.Close(); return; } IUser user = Users.Connect(res); // Enforce a maximum amount of connections per user if (Sessions.GetAvailableSessionCount(user) < 1) { ctx.Connection.Send(new AuthFailPacket(AuthFailReason.MaxSessions)); ctx.Connection.Close(); return; } ISession sess = Sessions.Create(ctx.Connection, user); sess.SendPacket(new WelcomeMessagePacket(Sender, $@"Welcome to Flashii Chat, {user.UserName}!")); if (File.Exists(WELCOME)) { IEnumerable <string> lines = File.ReadAllLines(WELCOME).Where(x => !string.IsNullOrWhiteSpace(x)); string line = lines.ElementAtOrDefault(RNG.Next(lines.Count())); if (!string.IsNullOrWhiteSpace(line)) { sess.SendPacket(new WelcomeMessagePacket(Sender, line)); } } IChannel chan = Channels.DefaultChannel; bool shouldJoin = !ChannelUsers.HasUser(chan, user); if (shouldJoin) { // ChannelUsers? //chan.SendPacket(new UserConnectPacket(DateTimeOffset.Now, user)); //ctx.Chat.DispatchEvent(this, new UserConnectEvent(chan, user)); } sess.SendPacket(new AuthSuccessPacket(user, chan, sess, Version, Messages.TextMaxLength)); ChannelUsers.GetUsers(chan, u => sess.SendPacket(new ContextUsersPacket(u.Except(new[] { user }).OrderByDescending(u => u.Rank)))); Messages.GetMessages(chan, m => { foreach (IMessage msg in m) { sess.SendPacket(new ContextMessagePacket(msg)); } }); Channels.GetChannels(user.Rank, c => sess.SendPacket(new ContextChannelsPacket(c))); if (shouldJoin) { ChannelUsers.JoinChannel(chan, sess); } }, exceptionHandler); }, exceptionHandler ); }
public void HandleCommand(ClientCommandContext ctx) { if (ctx.Connection.HasAuthenticated) { ctx.Connection.SendReply(new AlreadyRegisteredReply()); return; } // just drop subsequent calls if (ctx.Connection.IsAuthenticating) { return; } ctx.Connection.IsAuthenticating = true; string userName = ctx.Arguments.ElementAtOrDefault(0); string modeStr = ctx.Arguments.ElementAtOrDefault(1); //string param3 = ctx.Arguments.ElementAtOrDefault(2); //string realName = ctx.Arguments.ElementAtOrDefault(3); if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(modeStr)) { ctx.Connection.SendReply(new NeedMoreParamsReply(NAME)); return; } // TODO: should accept normal text username in the future!!!! if (!long.TryParse(userName, out long userId)) { ctx.Connection.SendReply(new PasswordMismatchReply()); ctx.Connection.Close(); return; } if (!int.TryParse(modeStr, out int mode)) { mode = 0; } bool isInvisible = (mode & MODE_I) > 0; bool receiveWallOps = (mode & MODE_W) > 0; Action <Exception> exceptionHandler = new Action <Exception>(ex => { Logger.Debug($@"[{ctx.Connection}] Auth fail: {ex.Message}"); ctx.Connection.SendReply(new PasswordMismatchReply()); ctx.Connection.Close(); }); DataProvider.UserAuthClient.AttemptAuth( new UserAuthRequest(userId, ctx.Connection.Password, ctx.Connection.RemoteAddress), res => { ctx.Connection.Password = null; ctx.Connection.HasAuthenticated = true; DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => { if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now) { // should probably include the time ctx.Connection.SendReply(new YouAreBannedReply(@"You have been banned.")); ctx.Connection.Close(); return; } Users.Connect(res, user => { Sessions.HasAvailableSessions(user, available => { // Enforce a maximum amount of connections per user if (!available) { // map somethign to this //ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.MaxSessions)); ctx.Connection.Close(); return; } Sessions.Create(ctx.Connection, user, session => { ctx.Connection.SendReply(new WelcomeReply(Server, user)); ctx.Connection.SendReply(new YourHostReply(Server)); ctx.Connection.SendReply(new CreatedReply(Context)); ctx.Connection.SendReply(new MyInfoReply(Server)); ctx.Connection.SendReply(new ISupportReply(Server)); if (WelcomeMessage.HasRandom) { ctx.Connection.SendReply(new MotdStartReply()); string line = WelcomeMessage.GetRandomString(); if (!string.IsNullOrWhiteSpace(line)) { ctx.Connection.SendReply(new MotdReply(line)); } ctx.Connection.SendReply(new MotdEndReply()); } else { ctx.Connection.SendReply(new NoMotdReply()); } // are these necessary? ctx.Connection.SendReply(new ListUserClientReply()); ctx.Connection.SendReply(new ListUserOperatorsReply()); ctx.Connection.SendReply(new ListUserUnknownReply()); ctx.Connection.SendReply(new ListUserChannelsReply()); ctx.Connection.SendReply(new ListUserMeReply()); Channels.GetDefaultChannels(channels => { foreach (IChannel channel in channels) { ChannelUsers.JoinChannel(channel, session); } }); }); }); }); }, exceptionHandler); }, exceptionHandler ); }