Chat-O-Matic/protocols/matrix/MatrixProtocol.cpp
Jaidyn Ann 604082466e (matrix) Init Matrix protocol
Just the scaffolding of a Matrix protocol using mtxclient: Room-joins
and (unencrypted) messages can be received, but everything's read-only
as yet. More to come!
2021-09-03 03:43:28 -05:00

272 lines
5.5 KiB
C++

/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "MatrixProtocol.h"
#include <Catalog.h>
#include <Messenger.h>
#include <Roster.h>
#include <libinterface/BitmapUtils.h>
#include <ChatProtocolMessages.h>
#include <UserStatus.h>
#include "Matrix.h"
#include "MatrixMessages.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MatrixProtocol"
status_t
connect_thread(void* data)
{
MatrixProtocol* protocol = (MatrixProtocol*)data;
while (true) {
BMessage* msg = new BMessage(receive_message());
switch (msg->what) {
case MATRIX_ACCOUNT_REGISTERED:
protocol->RegisterApp((team_id)msg->GetInt64("team_id", -1));
break;
default:
protocol->SendMessage(msg);
}
}
}
BMessage
receive_message()
{
thread_id sender;
int32 size = receive_data(&sender, NULL, 0);
char buffer[size];
receive_data(&sender, buffer, size);
BMessage temp;
temp.Unflatten(buffer);
return temp;
}
MatrixProtocol::MatrixProtocol()
:
fAppMessenger(NULL),
fAppTeam(-1)
{
}
MatrixProtocol::~MatrixProtocol()
{
Shutdown();
}
status_t
MatrixProtocol::Init(ChatProtocolMessengerInterface* interface)
{
fMessenger = interface;
return B_OK;
}
status_t
MatrixProtocol::Shutdown()
{
_SendMatrixMessage(new BMessage(B_QUIT_REQUESTED));
kill_thread(fRecvThread);
return B_OK;
}
status_t
MatrixProtocol::UpdateSettings(BMessage* settings)
{
fRecvThread = spawn_thread(connect_thread, "moon_w_blackjack_and_hookers",
B_NORMAL_PRIORITY, (void*)this);
if (fRecvThread < B_OK)
return B_ERROR;
settings->AddInt64("thread_id", fRecvThread);
fSettings = new BMessage(*settings);
return B_OK;
}
status_t
MatrixProtocol::Process(BMessage* msg)
{
int32 im_what = msg->GetInt32("im_what", -1);
switch (im_what) {
case IM_SET_OWN_STATUS:
{
int32 status = msg->GetInt32("status", -1);
switch (status) {
case STATUS_ONLINE:
resume_thread(fRecvThread);
if (fAppMessenger == NULL || fAppMessenger->IsValid() == false)
_StartApp();
break;
case STATUS_OFFLINE:
{
_SendMatrixMessage(new BMessage(B_QUIT_REQUESTED));
kill_thread(fRecvThread);
delete fAppMessenger;
fAppMessenger = NULL;
fAppTeam = -1;
break;
}
default:
_SendMatrixMessage(msg);
}
}
default:
_SendMatrixMessage(msg);
}
return B_OK;
}
BMessage
MatrixProtocol::SettingsTemplate(const char* name)
{
BMessage settings;
if (strcmp(name, "account") == 0)
settings = _AccountTemplate();
else if (strcmp(name, "join_room") == 0 || strcmp(name, "create_room") == 0)
settings = _RoomTemplate();
else if (strcmp(name, "roster") == 0)
settings = _RosterTemplate();
return settings;
}
BObjectList<BMessage>
MatrixProtocol::Commands()
{
return BObjectList<BMessage>();
}
BBitmap*
MatrixProtocol::Icon() const
{
return NULL;
// return ReadNodeIcon(fAddOnPath.Path(), B_LARGE_ICON, true);
}
void
MatrixProtocol::SendMessage(BMessage* msg)
{
msg->AddString("protocol", Signature());
fMessenger->SendMessage(msg);
}
void
MatrixProtocol::RegisterApp(team_id team)
{
if (team < 0)
return;
fAppTeam = team;
fAppMessenger = new BMessenger(NULL, team);
}
void
MatrixProtocol::_SendMatrixMessage(BMessage* msg)
{
msg->AddString("protocol", MATRIX_ADDON);
if (fAppMessenger != NULL && fAppMessenger->IsValid())
fAppMessenger->SendMessage(msg);
}
void
MatrixProtocol::_StartApp()
{
BMessage* start = new BMessage(*fSettings);
start->what = MATRIX_REGISTER_ACCOUNT;
BRoster roster;
if (roster.Launch(MATRIX_SIGNATURE, start) == B_OK)
snooze(100000);
}
BMessage
MatrixProtocol::_AccountTemplate()
{
BMessage settings;
BMessage server;
server.AddString("name", "server");
server.AddString("description", B_TRANSLATE("Homeserver:"));
server.AddString("default", "matrix.org");
server.AddString("error", B_TRANSLATE("Please enter a valid server address."));
server.AddInt32("type", B_STRING_TYPE);
settings.AddMessage("setting", &server);
BMessage user;
user.AddString("name", "username");
user.AddString("description", B_TRANSLATE("Username:"));
user.AddString("error", B_TRANSLATE("You need a username in order to connect!"));
user.AddInt32("type", B_STRING_TYPE);
settings.AddMessage("setting", &user);
BMessage password;
password.AddString("name", "password"); password.AddString("description", B_TRANSLATE("Password:"));
password.AddString("error", B_TRANSLATE("Without a password, how will love survive?"));
password.AddInt32("type", B_STRING_TYPE);
settings.AddMessage("setting", &password);
BMessage session;
session.AddString("name", "session");
session.AddString("description", B_TRANSLATE("Session name:"));
session.AddInt32("type", B_STRING_TYPE);
session.AddString("default", "Chat-O-Matic [Haiku]");
settings.AddMessage("setting", &session);
return settings;
}
BMessage
MatrixProtocol::_RoomTemplate()
{
BMessage settings;
BMessage id;
id.AddString("name", "chat_id");
id.AddString("description", B_TRANSLATE("Channel:"));
id.AddString("error", B_TRANSLATE("Please enter a channel― skipping it doesn't make sense!"));
id.AddInt32("type", B_STRING_TYPE);
settings.AddMessage("setting", &id);
return settings;
}
BMessage
MatrixProtocol::_RosterTemplate()
{
BMessage settings;
BMessage nick;
nick.AddString("name", "user_id");
nick.AddString("description", B_TRANSLATE("User ID:"));
nick.AddString("error", B_TRANSLATE("How can someone be your friend if you don't know their ID?"));
nick.AddInt32("type", B_STRING_TYPE);
settings.AddMessage("setting", &nick);
return settings;
}