From 0c615b01fd56ea2963d70dcfd3607fcbcb9a9c67 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Mon, 21 Jun 2021 01:54:42 -0500 Subject: [PATCH] Basic IRC connection/messaging/joining, etc. --- protocols/irc/IrcProtocol.cpp | 226 ++++++++++++++++++++++++++++++++-- protocols/irc/IrcProtocol.h | 30 ++++- 2 files changed, 247 insertions(+), 9 deletions(-) diff --git a/protocols/irc/IrcProtocol.cpp b/protocols/irc/IrcProtocol.cpp index 67d9605..000de1d 100644 --- a/protocols/irc/IrcProtocol.cpp +++ b/protocols/irc/IrcProtocol.cpp @@ -7,11 +7,21 @@ #include +#include + +#include + + +IrcProtocol* current_proto; + status_t connect_thread(void* data) { - BMessage* settings = (BMessage*)data; + IrcProtocol* proto = (IrcProtocol*)data; + current_proto = proto; + + BMessage* settings = proto->fSettings; if (!settings) return B_ERROR; @@ -32,11 +42,14 @@ connect_thread(void* data) joinServer << "#"; joinServer << server; - settings->PrintToStream(); - // Now create the session irc_callbacks_t callbacks = get_callbacks(); irc_session_t* session = irc_create_session(&callbacks); + proto->fSession = session; + + irc_ctx_t ctx; + ctx.nick.SetTo(nick); + irc_set_ctx(session, &ctx); if (!session) return B_ERROR; @@ -82,6 +95,61 @@ IrcProtocol::Shutdown() status_t IrcProtocol::Process(BMessage* msg) { + BString chat_id; + if (msg->FindString("chat_id", &chat_id) != B_OK) + return B_ERROR; + + switch (msg->FindInt32("im_what")) + { + case IM_SEND_MESSAGE: + { + BString body; + if (msg->FindString("body", &body) != B_OK) + return B_ERROR; + irc_cmd_msg(fSession, chat_id.String(), body.String()); + + irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(fSession); + + BMessage sendMsg(*msg); + sendMsg.ReplaceInt32("im_what", IM_MESSAGE_SENT); + sendMsg.AddString("user_id", ctx->id); + _SendMessage(&sendMsg); + break; + } + case IM_JOIN_ROOM: + case IM_CREATE_ROOM: + { + irc_cmd_join(fSession, chat_id.String(), ""); + break; + } + case IM_LEAVE_ROOM: + { + irc_cmd_part(fSession, chat_id.String()); + break; + } + case IM_GET_ROOM_PARTICIPANTS: + { + irc_cmd_names(fSession, chat_id.String()); + break; + } + case IM_ROOM_SEND_INVITE: + { + BString user_id; + if (msg->FindString("user_id", &user_id) != B_OK) + return B_ERROR; + irc_cmd_invite(fSession, user_id.String(), chat_id.String()); + break; + } + case IM_ROOM_KICK_PARTICIPANT: + { + BString user_id; + if (msg->FindString("user_id", &user_id) != B_OK) + return B_ERROR; + irc_cmd_kick(fSession, user_id.String(), chat_id.String(), + msg->FindString("body")); + break; + } + } return B_OK; } @@ -89,8 +157,9 @@ IrcProtocol::Process(BMessage* msg) status_t IrcProtocol::UpdateSettings(BMessage* msg) { + fSettings = msg; fServerThread = spawn_thread(connect_thread, "connect_thread", - B_NORMAL_PRIORITY, (void*)msg); + B_NORMAL_PRIORITY, (void*)this); if (fServerThread < B_OK) return B_ERROR; @@ -211,6 +280,10 @@ get_callbacks() callbacks.event_connect = event_connect; callbacks.event_numeric = event_numeric; callbacks.event_join = event_join; + callbacks.event_part = event_part; + callbacks.event_channel = event_channel; + callbacks.event_privmsg = event_privmsg; + callbacks.event_nick = event_nick; return callbacks; } @@ -219,18 +292,157 @@ void event_connect(irc_session_t* session, const char* event, const char* origin, const char** params, unsigned int count) { + BMessage readyMsg(IM_MESSAGE); + readyMsg.AddInt32("im_what", IM_PROTOCOL_READY); + _SendMessage(&readyMsg); } void -event_numeric(irc_session_t* session, unsigned int blah, +event_numeric(irc_session_t* session, unsigned int event, const char* origin, const char** params, unsigned int count) { + switch (event) { + case LIBIRC_RFC_RPL_NAMREPLY: + { + BStringList user_id; + BStringList user_name; + + BString user_list(params[3]); + user_list.Split(" ", false, user_id); + + BMessage list(IM_MESSAGE); + list.AddInt32("im_what", IM_ROOM_PARTICIPANTS); + list.AddString("chat_id", params[2]); + list.AddStrings("user_id", user_id); + list.AddStrings("user_name", user_id); + _SendMessage(&list); + break; + } + } } void -event_join(irc_session_t* session, const char* event, const char* origin, - const char** params, unsigned int count) +event_join(irc_session_t* session, const char* event, const char* joiner, + const char** channel, unsigned int count) { + int32 im_what = IM_ROOM_PARTICIPANT_JOINED; + + irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session); + if (_IsOwnUser(joiner, session) == true) + im_what = IM_ROOM_JOINED; + + BMessage joinedMsg(IM_MESSAGE); + joinedMsg.AddInt32("im_what", im_what); + joinedMsg.AddString("user_id", joiner); + joinedMsg.AddString("chat_id", channel[0]); + _SendMessage(&joinedMsg); +} + + +void +event_part(irc_session_t* session, const char* event, const char* quitter, + const char** chanReason, unsigned int count) +{ + int32 im_what = IM_ROOM_PARTICIPANT_LEFT; + if (_IsOwnUser(quitter, session) == true) + im_what = IM_ROOM_LEFT; + + BString body; + if (chanReason[1] != NULL) + body << chanReason[1]; + + BMessage quitMsg(IM_MESSAGE); + quitMsg.AddInt32("im_what", im_what); + quitMsg.AddString("user_id", quitter); + quitMsg.AddString("chat_id", chanReason[0]); + if (body.IsEmpty() == false) + quitMsg.AddString("body", body); + _SendMessage(&quitMsg); +} + + +void +event_channel(irc_session_t* session, const char* event, const char* sender, + const char** chanBody, unsigned int count) +{ + BMessage msgMsg(IM_MESSAGE); + msgMsg.AddInt32("im_what", IM_MESSAGE_RECEIVED); + msgMsg.AddString("user_id", sender); + msgMsg.AddString("chat_id", chanBody[0]); + msgMsg.AddString("body", chanBody[1]); + _SendMessage(&msgMsg); +} + + +void +event_privmsg(irc_session_t* session, const char* event, const char* sender, + const char** selfBody, unsigned int count) +{ + BMessage msgMsg(IM_MESSAGE); + msgMsg.AddInt32("im_what", IM_MESSAGE_RECEIVED); + msgMsg.AddString("user_id", sender); + msgMsg.AddString("chat_id", _UserNick(sender)); + msgMsg.AddString("body", selfBody[1]); + _SendMessage(&msgMsg); +} + + +// TODO: Nick-change API +void +event_nick(irc_session_t* session, const char* event, const char* oldNick, + const char** newNick, unsigned int count) +{ + irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session); + + if (_IsOwnUser(oldNick, session) == true) { + ctx->nick.SetTo(newNick[0]); + irc_set_ctx(session, ctx); + } +} + + +BString +_UserNick(const char* userId) +{ + BStringList split; + BString id(userId); + id.Split("!", false, split); + + return split.StringAt(0); +} + + +bool +_IsOwnUser(const char* userId, irc_session_t* session) +{ + bool ret = false; + irc_ctx_t* ctx = (irc_ctx_t*)irc_get_ctx(session); + + if (ctx->nick == _UserNick(userId)) { + ret = true; + if (ctx->id.IsEmpty() == true) { + ctx->id.SetTo(userId); + irc_set_ctx(session, ctx); + + // The app hasn't been informed of user_id, then! + BMessage ownInfo(IM_MESSAGE); + ownInfo.AddInt32("im_what", IM_OWN_CONTACT_INFO); + ownInfo.AddString("user_id", userId); + ownInfo.AddString("user_name", ctx->nick); + _SendMessage(&ownInfo); + } + } + return ret; +} + + +void +_SendMessage(BMessage* msg) +{ + if (!msg) + return; + msg->AddString("protocol", current_proto->Signature()); + current_proto->MessengerInterface()->SendMessage(msg); } diff --git a/protocols/irc/IrcProtocol.h b/protocols/irc/IrcProtocol.h index d5a91b3..1326eee 100644 --- a/protocols/irc/IrcProtocol.h +++ b/protocols/irc/IrcProtocol.h @@ -18,6 +18,14 @@ status_t connect_thread(void* data); +typedef struct +{ + BString nick; + BString id; +} irc_ctx_t; + + + class IrcProtocol : public ChatProtocol { public: IrcProtocol(); @@ -51,6 +59,9 @@ public: virtual ChatProtocolMessengerInterface* MessengerInterface() const; + // IRC + BMessage* fSettings; + irc_session_t* fSession; private: ChatProtocolMessengerInterface* fMessenger; @@ -69,11 +80,26 @@ void event_connect(irc_session_t* session, const char* event, const char* origin, const char** params, unsigned int count); -void event_numeric(irc_session_t* session, unsigned int blah, +void event_numeric(irc_session_t* session, unsigned int event, const char* origin, const char** params, unsigned int count); void event_join(irc_session_t* session, const char* event, - const char* origin, const char** params, unsigned int count); + const char* joiner, const char** channel, unsigned int count); +void event_part(irc_session_t* session, const char* event, + const char* quitter, const char** chanReason, unsigned int count); +void event_channel(irc_session_t* session, const char* event, + const char* sender, const char** chanBody, unsigned int count); +void event_privmsg(irc_session_t* session, const char* event, + const char* sender, const char** selfBody, unsigned int count); + +void event_nick(irc_session_t* session, const char* event, + const char* oldNick, const char** newNick, unsigned int count); + + +BString _UserNick(const char* userId); +bool _IsOwnUser(const char* userId, irc_session_t* session); + +void _SendMessage(BMessage* msg); #endif // _IRC_PROTOCOL_H