public void HandleCommand(ClientCommandContext ctx) { ctx.Connection.SendReply(new AdminMeReply()); ctx.Connection.SendReply(new AdminLocation1Reply()); ctx.Connection.SendReply(new AdminLocation2Reply()); ctx.Connection.SendReply(new AdminEMailReply()); }
public void HandleCommand(ClientCommandContext ctx) { IEnumerable <string> channelNames = (ctx.Arguments.FirstOrDefault() ?? string.Empty).Split(',').Select(n => n.ToLowerInvariant()); if (!channelNames.Any()) { ctx.Connection.SendReply(new NeedMoreParamsReply(NAME)); return; } foreach (string channelName in channelNames) { Channels.GetChannel(c => channelName.Equals(c.GetIRCName()), channel => { if (channel == null) { ctx.Connection.SendReply(new NoSuchChannelReply(channelName)); return; } ChannelUsers.HasSession(channel, ctx.Session, hasUser => { if (!hasUser) { ctx.Connection.SendReply(new NotOnChannelReply(channel)); return; } ChannelUsers.LeaveChannel(channel, ctx.Session); }); }); } }
public void HandleCommand(ClientCommandContext ctx) { string firstArg = ctx.Arguments.ElementAtOrDefault(0) ?? string.Empty; if (firstArg == @"0") // of course you would leave all channels with the JOIN command { ChannelUsers.LeaveChannels(ctx.Session); return; } string[] names = firstArg.Split(','); string[] passwords = (ctx.Arguments.ElementAtOrDefault(1) ?? string.Empty).Split(','); for (int i = 0; i < names.Length; ++i) { string name = names[i]; Channels.GetChannel(c => name.Equals(c.GetIRCName()), channel => { if (channel == null) // todo: check permissions and allow channel creation { ctx.Connection.SendReply(new BadChannelMaskReply(name)); return; } ChannelUsers.HasSession(channel, ctx.Session, hasSession => { // just continue if we're already in the channel if (hasSession) { return; } // introduce channel bans at some point // introduce invites at some point // add rank check ChannelUsers.CheckOverCapacity(channel, ctx.User, isOverCapacity => { if (isOverCapacity) { ctx.Connection.SendReply(new ChannelIsFullReply(channel)); return; } string password = passwords.ElementAtOrDefault(i) ?? string.Empty; Channels.VerifyPassword(channel, password, success => { if (!success) { ctx.Connection.SendReply(new BadChannelKeyReply(channel)); return; } ChannelUsers.JoinChannel(channel, ctx.Session); }); }); }); }); } }
public void HandleCommand(ClientCommandContext ctx) { ctx.Connection.SendReply( ctx.Arguments.Count() < 2 ? new NeedMoreParamsReply(NAME) : new NoOperatorHostReply() ); }
public void HandleCommand(ClientCommandContext ctx) { if (ctx.Arguments.Any()) { Sessions.DoKeepAlive(ctx.Session); ctx.Connection.SendCommand(new ServerPongCommand(Server, ctx.Arguments.FirstOrDefault())); } }
private void HandleChannel(ClientCommandContext ctx, IChannel channel) { Queue <string> args = new Queue <string>(ctx.Arguments); while (args.TryDequeue(out string arg)) { // } }
public void HandleCommand(ClientCommandContext ctx) { string line = ctx.Arguments.FirstOrDefault() ?? string.Empty; bool isAway = !string.IsNullOrEmpty(line); Users.Update( ctx.User, status: isAway ? UserStatus.Away : UserStatus.Online, statusMessage: line ); }
public void HandleCommand(ClientCommandContext ctx) { //string message = ctx.Arguments.ElementAtOrDefault(0); ctx.Connection.Close(); if (ctx.Session != null) { Sessions.Destroy(ctx.Connection); } }
public void HandleCommand(ClientCommandContext ctx) { if (ctx.User == null) // blocking calls to this without an error { return; } // TODO: check if user is allowed to set a nick // should prefixes be a thing for IRC? // should the prefix be nuked in favour of a forced name change? string nickName = ctx.Arguments.FirstOrDefault(); if (string.IsNullOrWhiteSpace(nickName)) { ctx.Connection.SendReply(new NoNickNameGivenReply()); return; } nickName = nickName.Trim(); if (nickName.Equals(ctx.User.UserName, StringComparison.InvariantCulture)) // allowing capitalisation changes { nickName = null; } else if (nickName.Length > 15) // should be configurable somewhere, also magic number in Sock Chat's impl { nickName = nickName.Substring(0, 15); // also Flashii's max username length is 16, guessing it was 15 to account for the ~? } else if (string.IsNullOrEmpty(nickName)) { nickName = null; } if (nickName == null) { Users.Update(ctx.User, nickName: string.Empty); return; } // TODO: global name validation routines //ctx.Connection.SendReply(new ErroneousNickNameReply(nickName)); Users.GetUser(nickName, user => { if (user != null) { ctx.Connection.SendReply(new NickNameInUseReply(nickName)); return; } Users.Update(ctx.User, nickName: nickName); }); }
public void HandleCommand(ClientCommandContext ctx) { string channelName = ctx.Arguments.ElementAtOrDefault(0); if (string.IsNullOrWhiteSpace(channelName)) { ctx.Connection.SendReply(new NoRecipientReply(NAME)); return; } string text = ctx.Arguments.ElementAtOrDefault(1); if (string.IsNullOrWhiteSpace(text)) { ctx.Connection.SendReply(new NoTextToSendReply()); return; } Func <IChannel, bool> predicate = null; char channelPrefix = channelName.First(); if (channelPrefix == '#') { predicate = new Func <IChannel, bool>(c => channelName.Equals(c.GetIRCName())); } if (predicate == null) { ctx.Connection.SendReply(new NoSuchNickReply(channelName)); return; } Channels.GetChannel(predicate, channel => { if (channel == null) { ctx.Connection.SendReply(new NoSuchNickReply(channelName)); return; } ChannelUsers.HasUser(channel, ctx.User, hasUser => { if (!hasUser) { ctx.Connection.SendReply(new CannotSendToChannelReply(channel)); return; } Messages.Create(ctx.Session, channel, text); }); }); }
private void HandleUser(ClientCommandContext ctx, IUser user) { HashSet <char> processed = new HashSet <char>(); string modeSet = ctx.Arguments.FirstOrDefault(); if (modeSet.Length < 2) { return; } Queue <char> chars = new Queue <char>(modeSet.ToArray()); char mode = chars.Dequeue(); if (mode != '+' && mode != '-') { return; } bool set = mode == '+'; while (chars.TryDequeue(out mode)) { if (processed.Contains(mode)) { continue; } processed.Add(mode); switch (mode) { case 'i': // Invisible (appear offline) Users.Update(user, status: set ? UserStatus.Offline : UserStatus.Online); break; default: ctx.Connection.SendReply(new UserModeUnknownFlagReply()); chars.Clear(); return; } } Sessions.CheckIRCSecure(user, isSecure => ctx.Connection.SendReply(new UserModeIsReply(user, isSecure))); }
public void HandleCommand(ClientCommandContext ctx) { if (ctx.Connection.HasAuthenticated) { ctx.Connection.SendReply(new AlreadyRegisteredReply()); return; } string password = ctx.Arguments.FirstOrDefault(); if (string.IsNullOrWhiteSpace(password)) { ctx.Connection.SendReply(new NeedMoreParamsReply(NAME)); return; } ctx.Connection.Password = password; }
public void HandleCommand(ClientCommandContext ctx) { string userName = ctx.Arguments.ElementAtOrDefault(0) ?? string.Empty; Users.GetUser(userName, user => { if (user == null) { ctx.Connection.SendReply(new NoSuchNickReply(userName)); return; } string channelName = ctx.Arguments.ElementAtOrDefault(1) ?? string.Empty; if (string.IsNullOrWhiteSpace(channelName)) { ctx.Connection.SendReply(new NoSuchChannelReply(channelName)); return; } Channels.GetChannelByName(channelName, channel => { if (channel == null) { ctx.Connection.SendReply(new NoSuchChannelReply(channelName)); return; } ChannelUsers.HasUser(channel, user, hasUser => { if (!hasUser) { ctx.Connection.SendReply(new UserOnChannelReply(user, channel)); return; } // todo: dispatch invite }); }); }); }
public void HandleCommand(ClientCommandContext ctx) { IEnumerable <string> userNames = ctx.Arguments.Select(u => u.ToLowerInvariant()); const int max_length = 400; // allow for 112 characters of overhead int length = 0; List <string> batch = new List <string>(); void sendBatch() { if (length < 1) { return; } ctx.Connection.SendReply(new IsOnReply(batch)); length = 0; batch.Clear(); }; Users.GetUsers(u => (u.Status == UserStatus.Online || u.Status == UserStatus.Away) && userNames.Contains(u.GetIRCName()), users => { foreach (IUser user in users) { string name = user.GetIRCName(); int nameLength = name.Length + 1; if (length + nameLength > max_length) { sendBatch(); } length += nameLength; batch.Add(name); } sendBatch(); }); }
public void HandleCommand(ClientCommandContext args) { // lists services, could be used for authentication but i think i'll just use the PASS field // not sure how i'm going to tackle auth entirely yet }
public void HandleCommand(ClientCommandContext args) { // }
public void HandleCommand(ClientCommandContext args) { // (un)silence people }
public void HandleCommand(ClientCommandContext ctx) { ctx.Connection.SendReply(new NoPrivilegesReply()); }
public void HandleCommand(ClientCommandContext args) { // lists users in channel, probably }
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 ); }
public void HandleCommand(ClientCommandContext args) { // like privmsg but autoreplies should not be sent // should this be supported? }
public void HandleCommand(ClientCommandContext args) { // returns version info }
public void HandleCommand(ClientCommandContext args) { // kick a user from a channel }
public void HandleCommand(ClientCommandContext args) { // returns server user stats }
public void HandleCommand(ClientCommandContext args) { // return info about users }
public void HandleCommand(ClientCommandContext args) { // gets or sets a channel topic }
public void HandleCommand(ClientCommandContext args) { // returns information about users }
public void HandleCommand(ClientCommandContext args) { // returns the MOTD }
public void HandleCommand(ClientCommandContext args) { // returns the obituary of a deceased user }
public void HandleCommand(ClientCommandContext ctx) { string targetName = ctx.Arguments.ElementAtOrDefault(0); if (string.IsNullOrWhiteSpace(targetName)) { ctx.Connection.SendReply(new NeedMoreParamsReply(NAME)); return; } if (!ctx.Arguments.Any()) { ctx.Connection.SendReply(new NeedMoreParamsReply(NAME)); return; } if (targetName.StartsWith('#')) { Channels.GetChannelByIRCName(targetName, channel => { if (channel == null) { ctx.Connection.SendReply(new NoSuchChannelReply(targetName)); return; } if (ctx.Arguments.Count() == 1) { //ctx.Connection.SendCommand(new ServerModeCommand(channel)); return; } // owner check HandleChannel(ctx, channel); }); } else { Users.GetUser(targetName, user => { if (user == null) { ctx.Connection.SendReply(new NoSuchNickReply(targetName)); return; } if (ctx.Arguments.Count() == 1) { //Sessions.CheckIRCSecure(user, isSecure => ctx.Connection.SendCommand(new ServerModeCommand(user, isSecure))); return; } if (!user.Equals(ctx.User)) { // admin check probably ctx.Connection.SendReply(new UsersDoNotMatchReply()); return; } HandleUser(ctx, user); }); } }