(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!
This commit is contained in:
Jaidyn Ann 2021-09-03 03:43:28 -05:00
parent 2f69f2fa04
commit 604082466e
10 changed files with 946 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

142
protocols/matrix/Makefile Normal file
View File

@ -0,0 +1,142 @@
## Haiku Generic Makefile v2.6 ##
## Fill in this file to specify the project being created, and the referenced
## Makefile-Engine will do all of the hard work for you. This handles any
## architecture of Haiku.
##
## For more information, see:
## file:///system/develop/documentation/makefile-engine.html
# The name of the binary.
NAME = chat-o-matic/matrix
# The type of binary, must be one of:
# APP: Application
# SHARED: Shared library or add-on
# STATIC: Static library archive
# DRIVER: Kernel driver
TYPE = APP
# If you plan to use localization, specify the application's MIME signature.
APP_MIME_SIG = application/x-vnd.chat-o-matic.matrix
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
# so that Pe and Eddie can fill them in for you.
#%{
# @src->@
# Specify the source files to use. Full paths or paths relative to the
# Makefile can be included. All files, regardless of directory, will have
# their object files created in the common object directory. Note that this
# means this Makefile will not work correctly if two source files with the
# same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile.
SRCS = \
protocols/matrix/MatrixApp.cpp \
protocols/matrix/MatrixMain.cpp \
protocols/matrix/MatrixProtocol.cpp \
# Specify the resource definition files to use. Full or relative paths can be
# used.
RDEFS = \
data/icons/protocols/IRC.rdef \
protocols/matrix/matrix.rdef \
# Specify the resource files to use. Full or relative paths can be used.
# Both RDEFS and RSRCS can be utilized in the same Makefile.
RSRCS =
# End Pe/Eddie support.
# @<-src@
#%}
# Specify libraries to link against.
# There are two acceptable forms of library specifications:
# - if your library follows the naming pattern of libXXX.so or libXXX.a,
# you can simply specify XXX for the library. (e.g. the entry for
# "libtracker.so" would be "tracker")
#
# - for GCC-independent linking of standard C++ libraries, you can use
# $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names.
#
# - if your library does not follow the standard library naming scheme,
# you need to specify the path to the library and it's name.
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
LIBS = be bnetapi localestub matrix_client network $(STDCPPLIBS)
# Specify additional paths to directories following the standard libXXX.so
# or libXXX.a naming scheme. You can specify full paths or paths relative
# to the Makefile. The paths included are not parsed recursively, so
# include all of the paths where libraries must be found. Directories where
# source files were specified are automatically included.
LIBPATHS =
# Additional paths to look for system headers. These use the form
# "#include <header>". Directories that contain the files in SRCS are
# NOT auto-included here.
SYSTEM_INCLUDE_PATHS = application/ libs/
# Additional paths paths to look for local headers. These use the form
# #include "header". Directories that contain the files in SRCS are
# automatically included.
LOCAL_INCLUDE_PATHS =
# Specify the level of optimization that you want. Specify either NONE (O0),
# SOME (O1), FULL (O3), or leave blank (for the default optimization level).
OPTIMIZE :=
# Specify the codes for languages you are going to support in this
# application. The default "en" one must be provided too. "make catkeys"
# will recreate only the "locales/en.catkeys" file. Use it as a template
# for creating catkeys for other languages. All localization files must be
# placed in the "locales" subdirectory.
LOCALES =
# Specify all the preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any) to
# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler
# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass
# "-DDEBUG" on the compiler's command line.
DEFINES =
# Specify the warning level. Either NONE (suppress all warnings),
# ALL (enable all warnings), or leave blank (enable default warnings).
WARNINGS =
# With image symbols, stack crawls in the debugger are meaningful.
# If set to "TRUE", symbols will be created.
SYMBOLS :=
# Includes debug information, which allows the binary to be debugged easily.
# If set to "TRUE", debug info will be created.
DEBUGGER :=
# Specify any additional compiler flags to be used.
COMPILER_FLAGS = -std=c++17
# Specify any additional linker flags to be used.
LINKER_FLAGS =
# Specify the version of this binary. Example:
# -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL"
# This may also be specified in a resource.
APP_VERSION :=
# (Only used when "TYPE" is "DRIVER"). Specify the desired driver install
# location in the /dev hierarchy. Example:
# DRIVER_PATH = video/usb
# will instruct the "driverinstall" rule to place a symlink to your driver's
# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will
# appear at /dev/video/usb when loaded. The default is "misc".
DRIVER_PATH =
## Include the Makefile-Engine
DEVEL_DIRECTORY := /boot/system/develop/
include $(DEVEL_DIRECTORY)/etc/makefile-engine
include Makefile.common
include protocols/Makefile.common
CATKEYS_DIR = locales/matrix

12
protocols/matrix/Matrix.h Normal file
View File

@ -0,0 +1,12 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _MATRIX_H
#define _MATRIX_H
#define MATRIX_SIGNATURE "application/x-vnd.chat-o-matic.matrix"
#define MATRIX_ADDON "matrix"
#endif // _MATRIX_H

View File

@ -0,0 +1,299 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "MatrixApp.h"
#include <iostream>
#include <string>
#include <Catalog.h>
#include <MessageRunner.h>
#include <Roster.h>
#include <ChatOMatic.h>
#include <ChatProtocolMessages.h>
#include <Flags.h>
#include <UserStatus.h>
#include "Matrix.h"
#include "MatrixMessages.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MatrixApp"
std::shared_ptr<mtx::http::Client> client = nullptr;
MatrixApp* m_app = NULL;
int
main(int arc, char** argv)
{
MatrixApp app;
app.Run();
return 0;
}
MatrixApp::MatrixApp()
:
BApplication(MATRIX_SIGNATURE),
fUser(NULL),
fPassword(NULL),
fInitStatus(B_NOT_INITIALIZED),
fProtoThread(-1)
{
new BMessageRunner(this, new BMessage(CHECK_APP), 10000000, -1);
}
void
MatrixApp::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case MATRIX_REGISTER_ACCOUNT:
{
int64 thread_id;
if (msg->FindInt64("thread_id", &thread_id) != B_OK)
break;
fProtoThread = thread_id;
fUser = msg->FindString("username");
fSession = msg->GetString("session", "Chat-O-Matic [Haiku]");
fServer = msg->FindString("server");
fPassword = msg->FindString("password");
app_info info;
GetAppInfo(&info);
BMessage registerApp(MATRIX_ACCOUNT_REGISTERED);
registerApp.AddInt64("team_id", info.team);
SendMessage(registerApp);
Connect();
break;
}
case CHECK_APP:
{
BRoster roster;
if (roster.IsRunning(APP_SIGNATURE) == false)
Quit();
break;
}
default:
BApplication::MessageReceived(msg);
}
}
void
MatrixApp::ImMessage(BMessage* msg)
{
int32 im_what = msg->GetInt32("im_what", -1);
switch (im_what) {
case IM_SET_OWN_STATUS:
{
}
default: {
std::cout << "Unhandled message for Matrix:\n";
msg->PrintToStream();
}
}
}
void
MatrixApp::Connect()
{
client = std::make_shared<mtx::http::Client>(fServer.String());
client->set_device_id(fSession.String());
client->login(fUser.String(), fPassword.String(),
[this](const mtx::responses::Login &res, mtx::http::RequestErr err)
{
if (err) {
SendError("Error occured during login, please try again.", err,
true);
fInitStatus = B_ERROR;
}
else {
client->set_access_token(res.access_token);
fInitStatus = B_OK;
StartLoop();
}
});
}
void
MatrixApp::StartLoop()
{
BMessage ready(IM_MESSAGE);
ready.AddInt32("im_what", IM_PROTOCOL_READY);
SendMessage(ready);
BString mxId("@");
mxId << fUser << ":" << fServer;
BMessage init(IM_MESSAGE);
init.AddInt32("im_what", IM_OWN_CONTACT_INFO);
init.AddString("user_id", mxId);
SendMessage(init);
BMessage status(IM_MESSAGE);
status.AddInt32("im_what", IM_OWN_STATUS_SET);
status.AddInt32("status", (int32)STATUS_ONLINE);
SendMessage(status);
mtx::http::SyncOpts opts;
opts.timeout = 0;
client->sync(opts, &initial_sync_handler);
client->close();
}
void
MatrixApp::SendMessage(BMessage msg)
{
if (fProtoThread <= 0)
return;
ssize_t size = msg.FlattenedSize();
char buffer[size];
send_data(fProtoThread, size, NULL, 0);
msg.Flatten(buffer, size);
send_data(fProtoThread, 0, buffer, size);
}
void
MatrixApp::SendError(const char* message, mtx::http::RequestErr err,
bool fatal)
{
print_error(err);
BString detail;
if (!err->matrix_error.error.empty())
detail << err->matrix_error.error.c_str();
BMessage error(IM_ERROR);
error.AddString("error", message);
error.AddString("detail", detail);
SendMessage(error);
if (fatal == true) {
BMessage disable(IM_MESSAGE);
disable.AddInt32("im_what", IM_PROTOCOL_DISABLE);
SendMessage(disable);
}
}
void
print_error(mtx::http::RequestErr err, const char* message)
{
if (message != NULL)
std::cerr << message << "";
std::cerr << err->status_code << " : " << err->error_code;
if (!err->matrix_error.error.empty())
std::cerr << " : " << err->matrix_error.error;
std::cerr << std::endl;
}
void
initial_sync_handler(const mtx::responses::Sync &res, mtx::http::RequestErr err)
{
mtx::http::SyncOpts opts;
if (err) {
print_error(err, "Error occured during initial sync. Retrying…");
if ((int)err->status_code != 200) {
opts.timeout = 0;
client->sync(opts, &initial_sync_handler);
}
return;
}
room_sync(res.rooms);
opts.since = res.next_batch;
client->set_next_batch_token(res.next_batch);
client->sync(opts, &sync_handler);
}
// Callback to executed after a /sync request completes.
void
sync_handler(const mtx::responses::Sync &res, mtx::http::RequestErr err)
{
mtx::http::SyncOpts opts;
if (err) {
print_error(err, "Error occured during sync. Retrying…");
opts.since = client->next_batch_token();
client->sync(opts, &sync_handler);
return;
}
room_sync(res.rooms);
opts.since = res.next_batch;
client->set_next_batch_token(res.next_batch);
client->sync(opts, &sync_handler);
}
void
room_sync(mtx::responses::Rooms rooms)
{
MatrixApp* app = (MatrixApp*)be_app;
std::map<std::string, mtx::responses::JoinedRoom> joined = rooms.join;
for (std::map<std::string, mtx::responses::JoinedRoom>::iterator iter
= joined.begin();
iter != joined.end();
++iter)
{
const char* chat_id = iter->first.c_str();
mtx::responses::JoinedRoom room = iter->second;
if (app->fRoomList.HasString(BString(chat_id)) == false) {
BMessage joinedMsg(IM_MESSAGE);
joinedMsg.AddInt32("im_what", IM_ROOM_JOINED);
joinedMsg.AddString("chat_id", chat_id);
((MatrixApp*)be_app)->SendMessage(joinedMsg);
app->fRoomList.Add(BString(chat_id));
}
for (mtx::events::collections::TimelineEvents &ev : room.timeline.events)
if (auto event = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Text>>(&ev);
event != nullptr)
{
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
msg.AddString("body", event->content.body.c_str());
msg.AddString("chat_id", chat_id);
msg.AddString("user_id", event->sender.c_str());
app->SendMessage(msg);
}
}
std::map<std::string, mtx::responses::LeftRoom> left = rooms.leave;
for (std::map<std::string, mtx::responses::LeftRoom>::iterator iter
= left.begin();
iter != left.end();
++iter)
{
const char* chat_id = iter->first.c_str();
if (app->fRoomList.HasString(BString(chat_id)) == true)
app->fRoomList.Remove(BString(chat_id));
BMessage leftMsg(IM_MESSAGE);
leftMsg.AddInt32("im_what", IM_ROOM_LEFT);
leftMsg.AddString("chat_id", ((std::string)iter->first).c_str());
((MatrixApp*)be_app)->SendMessage(leftMsg);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _MATRIX_APP_H
#define _MATRIX_APP_H
#include <Application.h>
#include <String.h>
#include <StringList.h>
#include <mtx.hpp>
#include <mtxclient/http/client.hpp>
#include <mtxclient/http/errors.hpp>
const uint32 CHECK_APP = 'Paca';
class MatrixApp : public BApplication {
public:
MatrixApp();
virtual void MessageReceived(BMessage* msg);
void ImMessage(BMessage* msg);
void Connect();
void StartLoop();
void SendMessage(BMessage msg);
void SendError(const char* message,
mtx::http::RequestErr err, bool fatal = false);
BMessage* fSettings;
status_t fInitStatus;
BStringList fRoomList;
private:
// Settings
BString fUser;
BString fPassword;
BString fServer;
BString fSession;
thread_id fProtoThread;
};
void print_error(mtx::http::RequestErr err, const char* message = NULL);
void login_handler(const mtx::responses::Login &res, mtx::http::RequestErr err);
void initial_sync_handler(const mtx::responses::Sync &res, mtx::http::RequestErr err);
void sync_handler(const mtx::responses::Sync &res, mtx::http::RequestErr err);
void room_sync(mtx::responses::Rooms rooms);
#endif // _MATRIX_APP_H

View File

@ -0,0 +1,50 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "MatrixProtocol.h"
extern "C" _EXPORT ChatProtocol* protocol_at(int32 i);
extern "C" _EXPORT int32 protocol_count();
extern "C" _EXPORT const char* signature();
extern "C" _EXPORT const char* friendly_signature();
extern "C" _EXPORT uint32 version();
ChatProtocol*
protocol_at(int32 i)
{
if (i == 0)
return (ChatProtocol*)new MatrixProtocol();
return NULL;
}
int32
protocol_count()
{
return 1;
}
const char*
signature()
{
return "matrix";
}
const char*
friendly_signature()
{
return "Matrix";
}
uint32
version()
{
return APP_VERSION_1_ALPHA_1;
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _MATRIX_MESSAGES_H
#define _MATRIX_MESSAGES_H
enum matrix_message {
/*
* Messages between the Matrix add-on and server
*/
/*! Register account & thread with app →Server
Requires: Account template, int64 thread_id */
MATRIX_REGISTER_ACCOUNT = 'MXra',
/*! Inform the protocol of app team id →Protocol
Requires: int64 team_id */
MATRIX_ACCOUNT_REGISTERED = 'MXar'
};
#endif // _MATRIX_MESSAGES_H

View File

@ -0,0 +1,271 @@
/*
* 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;
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _MATRIX_PROTOCOL_H
#define _MATRIX_PROTOCOL_H
#include <String.h>
#include <ChatProtocol.h>
#include "Matrix.h"
status_t connect_thread(void* data);
BMessage receive_message();
class MatrixProtocol : public ChatProtocol {
public:
MatrixProtocol();
~MatrixProtocol();
// ChatProtocol inheritance
virtual status_t Init(ChatProtocolMessengerInterface* interface);
virtual status_t Shutdown();
virtual status_t UpdateSettings(BMessage* settings);
virtual status_t Process(BMessage* msg);
virtual BMessage SettingsTemplate(const char* name);
virtual BObjectList<BMessage>
Commands();
virtual const char* Signature() const { return MATRIX_ADDON; }
virtual const char* FriendlySignature() const { return "Matrix"; }
virtual BBitmap* Icon() const;
virtual void SetAddOnPath(BPath path) { fAddOnPath = path; }
virtual BPath AddOnPath() { return fAddOnPath; }
virtual const char* GetName() { return fName; }
virtual void SetName(const char* name) { fName = name; }
virtual ChatProtocolMessengerInterface*
MessengerInterface() const { return fMessenger; }
// Matrix
void SendMessage(BMessage* msg);
void RegisterApp(team_id team);
private:
void _SendMatrixMessage(BMessage* msg);
void _StartApp();
// GUI templates
BMessage _AccountTemplate();
BMessage _RoomTemplate();
BMessage _RosterTemplate();
// Settings
BMessage* fSettings;
BPath fAddOnPath;
BString fName;
ChatProtocolMessengerInterface* fMessenger;
team_id fAppTeam;
thread_id fRecvThread;
BMessenger* fAppMessenger;
};
#endif // _MATRIX_PROTOCOL_H

View File

@ -0,0 +1,16 @@
#include "Matrix.h"
resource app_signature MATRIX_SIGNATURE;
resource app_flags B_BACKGROUND_APP | B_MULTIPLE_LAUNCH;
resource app_version {
major = 0,
middle = 0,
minor = 1,
variety = B_APPV_ALPHA,
internal = 0,
short_info = "Chat-O-Matic Matrix add-on",
long_info = "©2021 Jaidyn Levesque"
};