diff --git a/Applications/IRCClient/IRCAppWindow.cpp b/Applications/IRCClient/IRCAppWindow.cpp index 6b3e455bca..6b71136d10 100644 --- a/Applications/IRCClient/IRCAppWindow.cpp +++ b/Applications/IRCClient/IRCAppWindow.cpp @@ -168,6 +168,14 @@ void IRCAppWindow::setup_actions() m_client->handle_invite_user_action(window->channel().name(), input_box->text_value()); }); + m_banlist_action = GUI::Action::create("Ban list", [this](auto&) { + auto* window = m_client->current_window(); + if (!window || window->type() != IRCWindow::Type::Channel) { + return; + } + m_client->handle_banlist_action(window->channel().name()); + }); + m_voice_user_action = GUI::Action::create("Voice user", [this](auto&) { auto* window = m_client->current_window(); if (!window || window->type() != IRCWindow::Type::Channel) { @@ -252,6 +260,7 @@ void IRCAppWindow::setup_menus() auto& channel_menu = menubar->add_menu("Channel"); channel_menu.add_action(*m_change_topic_action); channel_menu.add_action(*m_invite_user_action); + channel_menu.add_action(*m_banlist_action); channel_menu.add_separator(); channel_menu.add_action(*m_voice_user_action); channel_menu.add_action(*m_devoice_user_action); @@ -329,6 +338,7 @@ void IRCAppWindow::update_gui_actions() bool is_open_channel = window && window->type() == IRCWindow::Type::Channel && window->channel().is_open(); m_change_topic_action->set_enabled(is_open_channel); m_invite_user_action->set_enabled(is_open_channel); + m_banlist_action->set_enabled(is_open_channel); m_voice_user_action->set_enabled(is_open_channel); m_devoice_user_action->set_enabled(is_open_channel); m_op_user_action->set_enabled(is_open_channel); diff --git a/Applications/IRCClient/IRCAppWindow.h b/Applications/IRCClient/IRCAppWindow.h index 03f20fb964..71a4ed631e 100644 --- a/Applications/IRCClient/IRCAppWindow.h +++ b/Applications/IRCClient/IRCAppWindow.h @@ -64,6 +64,7 @@ private: RefPtr m_change_nick_action; RefPtr m_change_topic_action; RefPtr m_invite_user_action; + RefPtr m_banlist_action; RefPtr m_voice_user_action; RefPtr m_devoice_user_action; RefPtr m_op_user_action; diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp index 74eb210403..3c81596b02 100644 --- a/Applications/IRCClient/IRCClient.cpp +++ b/Applications/IRCClient/IRCClient.cpp @@ -48,6 +48,7 @@ enum IRCNumeric { RPL_WHOISUSER = 311, RPL_WHOISSERVER = 312, RPL_WHOISOPERATOR = 313, + RPL_ENDOFWHO = 315, RPL_WHOISIDLE = 317, RPL_ENDOFWHOIS = 318, RPL_WHOISCHANNELS = 319, @@ -55,7 +56,13 @@ enum IRCNumeric { RPL_TOPICWHOTIME = 333, RPL_NAMREPLY = 353, RPL_ENDOFNAMES = 366, - RPL_ERR_UNKNOWNCOMMAND = 421, + RPL_BANLIST = 367, + RPL_ENDOFBANLIST = 368, + RPL_ENDOFWHOWAS = 369, + RPL_ENDOFMOTD = 376, + ERR_NOSUCHNICK = 401, + ERR_UNKNOWNCOMMAND = 421, + ERR_NICKNAMEINUSE = 433, }; IRCClient::IRCClient() @@ -261,8 +268,14 @@ void IRCClient::handle(const Message& msg) switch (numeric) { case RPL_WHOISCHANNELS: return handle_rpl_whoischannels(msg); + case RPL_ENDOFWHO: + return handle_rpl_endofwho(msg); case RPL_ENDOFWHOIS: return handle_rpl_endofwhois(msg); + case RPL_ENDOFWHOWAS: + return handle_rpl_endofwhowas(msg); + case RPL_ENDOFMOTD: + return handle_rpl_endofmotd(msg); case RPL_WHOISOPERATOR: return handle_rpl_whoisoperator(msg); case RPL_WHOISSERVER: @@ -279,8 +292,16 @@ void IRCClient::handle(const Message& msg) return handle_rpl_namreply(msg); case RPL_ENDOFNAMES: return handle_rpl_endofnames(msg); - case RPL_ERR_UNKNOWNCOMMAND: - return handle_rpl_unknowncommand(msg); + case RPL_BANLIST: + return handle_rpl_banlist(msg); + case RPL_ENDOFBANLIST: + return handle_rpl_endofbanlist(msg); + case ERR_NOSUCHNICK: + return handle_err_nosuchnick(msg); + case ERR_UNKNOWNCOMMAND: + return handle_err_unknowncommand(msg); + case ERR_NICKNAMEINUSE: + return handle_err_nicknameinuse(msg); } } @@ -328,6 +349,11 @@ void IRCClient::send_invite(const String& channel_name, const String& nick) send(String::format("INVITE %s %s\r\n", nick.characters(), channel_name.characters())); } +void IRCClient::send_banlist(const String& channel_name) +{ + send(String::format("MODE %s +b\r\n", channel_name.characters())); +} + void IRCClient::send_voice_user(const String& channel_name, const String& nick) { send(String::format("MODE %s +v %s\r\n", channel_name.characters(), nick.characters())); @@ -630,6 +656,28 @@ void IRCClient::handle_rpl_namreply(const Message& msg) void IRCClient::handle_rpl_endofnames(const Message&) { + add_server_message("// End of NAMES"); +} + +void IRCClient::handle_rpl_banlist(const Message& msg) +{ + if (msg.arguments.size() < 5) + return; + auto& channel = msg.arguments[1]; + auto& mask = msg.arguments[2]; + auto& user = msg.arguments[3]; + auto& datestamp = msg.arguments[4]; + add_server_message(String::format("* %s: %s on %s by %s", channel.characters(), mask.characters(), datestamp.characters(), user.characters())); +} + +void IRCClient::handle_rpl_endofbanlist(const Message&) +{ + add_server_message("// End of BANLIST"); +} + +void IRCClient::handle_rpl_endofwho(const Message&) +{ + add_server_message("// End of WHO"); } void IRCClient::handle_rpl_endofwhois(const Message&) @@ -637,6 +685,16 @@ void IRCClient::handle_rpl_endofwhois(const Message&) add_server_message("// End of WHOIS"); } +void IRCClient::handle_rpl_endofwhowas(const Message&) +{ + add_server_message("// End of WHOWAS"); +} + +void IRCClient::handle_rpl_endofmotd(const Message&) +{ + add_server_message("// End of MOTD"); +} + void IRCClient::handle_rpl_whoisoperator(const Message& msg) { if (msg.arguments.size() < 2) @@ -703,7 +761,16 @@ void IRCClient::handle_rpl_topicwhotime(const Message& msg) ensure_channel(channel_name).add_message(String::format("*** (set by %s at %s)", nick.characters(), setat.characters()), Color::Blue); } -void IRCClient::handle_rpl_unknowncommand(const Message& msg) +void IRCClient::handle_err_nosuchnick(const Message& msg) +{ + if (msg.arguments.size() < 3) + return; + auto& nick = msg.arguments[1]; + auto& message = msg.arguments[2]; + add_server_message(String::format("* %s :%s", nick.characters(), message.characters())); +} + +void IRCClient::handle_err_unknowncommand(const Message& msg) { if (msg.arguments.size() < 2) return; @@ -711,6 +778,14 @@ void IRCClient::handle_rpl_unknowncommand(const Message& msg) add_server_message(String::format("* Unknown command: %s", cmd.characters())); } +void IRCClient::handle_err_nicknameinuse(const Message& msg) +{ + if (msg.arguments.size() < 2) + return; + auto& nick = msg.arguments[1]; + add_server_message(String::format("* %s :Nickname in use", nick.characters())); +} + void IRCClient::register_subwindow(IRCWindow& subwindow) { if (subwindow.type() == IRCWindow::Server) { @@ -787,6 +862,19 @@ void IRCClient::handle_user_command(const String& input) } return; } + if (command == "/BANLIST") { + if (parts.size() >= 2) { + auto channel = parts[1]; + send_banlist(channel); + } else { + auto* window = current_window(); + if (!window || window->type() != IRCWindow::Type::Channel) + return; + auto channel = window->channel().name(); + send_banlist(channel); + } + return; + } if (command == "/TOPIC") { if (parts.size() < 2) return; @@ -895,6 +983,11 @@ void IRCClient::handle_invite_user_action(const String& channel, const String& n send_invite(channel, nick); } +void IRCClient::handle_banlist_action(const String& channel) +{ + send_banlist(channel); +} + void IRCClient::handle_voice_user_action(const String& channel, const String& nick) { send_voice_user(channel, nick); diff --git a/Applications/IRCClient/IRCClient.h b/Applications/IRCClient/IRCClient.h index 84e1429a5c..9c3089a02d 100644 --- a/Applications/IRCClient/IRCClient.h +++ b/Applications/IRCClient/IRCClient.h @@ -110,6 +110,7 @@ public: void handle_change_nick_action(const String& nick); void handle_change_topic_action(const String& channel_name, const String&); void handle_invite_user_action(const String& channel_name, const String& nick); + void handle_banlist_action(const String& channel_name); void handle_voice_user_action(const String& channel_name, const String& nick); void handle_devoice_user_action(const String& channel_name, const String& nick); void handle_op_user_action(const String& channel_name, const String& nick); @@ -145,6 +146,7 @@ private: void send_notice(const String& target, const String&); void send_topic(const String& channel_name, const String&); void send_invite(const String& channel_name, const String& nick); + void send_banlist(const String& channel_name); void send_voice_user(const String& channel_name, const String& nick); void send_devoice_user(const String& channel_name, const String& nick); void send_op_user(const String& channel_name, const String& nick); @@ -163,12 +165,19 @@ private: void handle_rpl_whoisserver(const Message&); void handle_rpl_whoisoperator(const Message&); void handle_rpl_whoisidle(const Message&); + void handle_rpl_endofwho(const Message&); void handle_rpl_endofwhois(const Message&); + void handle_rpl_endofwhowas(const Message&); + void handle_rpl_endofmotd(const Message&); void handle_rpl_whoischannels(const Message&); void handle_rpl_topicwhotime(const Message&); void handle_rpl_endofnames(const Message&); + void handle_rpl_endofbanlist(const Message&); void handle_rpl_namreply(const Message&); - void handle_rpl_unknowncommand(const Message&); + void handle_rpl_banlist(const Message&); + void handle_err_nosuchnick(const Message&); + void handle_err_unknowncommand(const Message&); + void handle_err_nicknameinuse(const Message&); void handle_privmsg_or_notice(const Message&, PrivmsgOrNotice); void handle_nick(const Message&); void handle(const Message&);