summaryrefslogtreecommitdiff
path: root/Applications/IRCClient/IRCClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Applications/IRCClient/IRCClient.cpp')
-rw-r--r--Applications/IRCClient/IRCClient.cpp69
1 files changed, 65 insertions, 4 deletions
diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp
index 8847270438..2b93fba7c3 100644
--- a/Applications/IRCClient/IRCClient.cpp
+++ b/Applications/IRCClient/IRCClient.cpp
@@ -1,10 +1,11 @@
-#include "IRCAppWindow.h"
#include "IRCClient.h"
+#include "IRCAppWindow.h"
#include "IRCChannel.h"
#include "IRCLogBuffer.h"
#include "IRCQuery.h"
#include "IRCWindow.h"
#include "IRCWindowListModel.h"
+#include <AK/StringBuilder.h>
#include <LibCore/CNotifier.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -291,6 +292,11 @@ void IRCClient::send_privmsg(const String& target, const String& text)
send(String::format("PRIVMSG %s :%s\r\n", target.characters(), text.characters()));
}
+void IRCClient::send_notice(const String& target, const String& text)
+{
+ send(String::format("NOTICE %s :%s\r\n", target.characters(), text.characters()));
+}
+
void IRCClient::handle_user_input_in_channel(const String& channel_name, const String& input)
{
if (input.is_empty())
@@ -330,6 +336,11 @@ bool IRCClient::is_nick_prefix(char ch) const
return false;
}
+static bool has_ctcp_payload(const StringView& string)
+{
+ return string.length() >= 2 && string[0] == 0x01 && string[string.length() - 1] == 0x01;
+}
+
void IRCClient::handle_privmsg_or_notice(const Message& msg, PrivmsgOrNotice type)
{
if (msg.arguments.size() < 2)
@@ -340,9 +351,12 @@ void IRCClient::handle_privmsg_or_notice(const Message& msg, PrivmsgOrNotice typ
auto sender_nick = parts[0];
auto target = msg.arguments[0];
+ bool is_ctcp = has_ctcp_payload(msg.arguments[1]);
+
#ifdef IRC_DEBUG
- printf("handle_privmsg_or_notice: type='%s', sender_nick='%s', target='%s'\n",
+ printf("handle_privmsg_or_notice: type='%s'%s, sender_nick='%s', target='%s'\n",
type == PrivmsgOrNotice::Privmsg ? "privmsg" : "notice",
+ is_ctcp ? " (ctcp)" : "",
sender_nick.characters(),
target.characters());
#endif
@@ -356,15 +370,31 @@ void IRCClient::handle_privmsg_or_notice(const Message& msg, PrivmsgOrNotice typ
sender_nick = sender_nick.substring(1, sender_nick.length() - 1);
}
+ String message_text = msg.arguments[1];
+ auto message_color = Color::Black;
+
+ if (is_ctcp) {
+ auto ctcp_payload = msg.arguments[1].substring_view(1, msg.arguments[1].length() - 2);
+ if (type == PrivmsgOrNotice::Privmsg)
+ handle_ctcp_request(sender_nick, ctcp_payload);
+ else
+ handle_ctcp_response(sender_nick, ctcp_payload);
+ StringBuilder builder;
+ builder.append("(CTCP) ");
+ builder.append(ctcp_payload);
+ message_text = builder.to_string();
+ message_color = Color::Blue;
+ }
+
{
auto it = m_channels.find(target);
if (it != m_channels.end()) {
- (*it).value->add_message(sender_prefix, sender_nick, msg.arguments[1]);
+ (*it).value->add_message(sender_prefix, sender_nick, message_text, message_color);
return;
}
}
auto& query = ensure_query(sender_nick);
- query.add_message(sender_prefix, sender_nick, msg.arguments[1]);
+ query.add_message(sender_prefix, sender_nick, message_text, message_color);
}
IRCQuery& IRCClient::ensure_query(const String& name)
@@ -671,3 +701,34 @@ void IRCClient::did_part_from_channel(Badge<IRCChannel>, IRCChannel& channel)
if (on_part_from_channel)
on_part_from_channel(channel);
}
+
+void IRCClient::send_ctcp_response(const StringView& peer, const StringView& payload)
+{
+ StringBuilder builder;
+ builder.append(0x01);
+ builder.append(payload);
+ builder.append(0x01);
+ auto message = builder.to_string();
+ send_notice(peer, message);
+}
+
+void IRCClient::handle_ctcp_request(const StringView& peer, const StringView& payload)
+{
+ dbg() << "handle_ctcp_request: " << payload;
+
+ if (payload == "VERSION") {
+ send_ctcp_response(peer, "VERSION IRC Client [x86] / Serenity OS");
+ return;
+ }
+
+ // FIXME: Add StringView::starts_with()
+ if (String(payload).starts_with("PING")) {
+ send_ctcp_response(peer, payload);
+ return;
+ }
+}
+
+void IRCClient::handle_ctcp_response(const StringView& peer, const StringView& payload)
+{
+ dbg() << "handle_ctcp_response(" << peer << "): " << payload;
+}