Chat-O-Matic/application/Server.cpp

1013 lines
23 KiB
C++
Raw Normal View History

/*
2011-12-03 16:38:03 -06:00
* Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2009-2011, Pier Luigi Fiorini. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Andrea Anzani, andrea.anzani@gmail.com
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
* Jaidyn Levesque, jadedctrl@teknik.io
*
* Contributors:
* Dario Casalinuovo
*/
#include "Server.h"
#include <Application.h>
2021-07-19 09:54:27 -05:00
#include <Catalog.h>
#include <Debug.h>
#include <Entry.h>
2010-05-30 07:17:32 -05:00
#include <Notification.h>
#include <Path.h>
#include <StringList.h>
#include <TranslationUtils.h>
#include "Account.h"
#include "AccountManager.h"
2021-06-20 12:44:20 -05:00
#include "AppMessages.h"
2021-06-22 01:06:00 -05:00
#include "Cardie.h"
2021-06-20 12:44:20 -05:00
#include "ChatProtocol.h"
#include "AppPreferences.h"
#include "ChatProtocolMessages.h"
#include "Flags.h"
#include "ImageCache.h"
#include "InviteDialogue.h"
#include "ProtocolLooper.h"
#include "ProtocolManager.h"
#include "RosterItem.h"
#include "UserInfoWindow.h"
2021-06-20 12:44:20 -05:00
#include "Utils.h"
2021-07-19 09:54:27 -05:00
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Server"
Server::Server()
2010-05-19 17:28:26 -05:00
:
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
{
if (fChatItems.IsEmpty() == false || fUserItems.IsEmpty() == false
|| fCommands.CountItems() > 0)
return;
BResources* res = ChatResources();
// Loading user pop-up items
for (int i = 0; i < 6; i++) {
size_t size;
BMessage temp;
const void* buff = res->LoadResource(B_MESSAGE_TYPE, 1100 + i, &size);
temp.Unflatten((const char*)buff);
fUserItems.AddItem(new BMessage(temp));
}
// Loading room pop-up items
BMessage leave;
size_t leaveSize;
const void* leaveBuff = res->LoadResource(B_MESSAGE_TYPE, 1120, &leaveSize);
leave.Unflatten((const char*)leaveBuff);
fChatItems.AddItem(new BMessage(leave));
// Loading default chat commands
for (int i = 0; i < 9; i++) {
size_t size;
BMessage temp;
const void* buff = res->LoadResource(B_MESSAGE_TYPE, 1140 + i, &size);
temp.Unflatten((const char*)buff);
ChatCommand* cmd = new ChatCommand(&temp);
fCommands.AddItem(cmd->GetName(), cmd);
}
}
2010-05-19 17:28:26 -05:00
void
Server::Quit()
{
for (int i = 0; i < fLoopers.CountItems(); i++)
RemoveProtocolLooper(fLoopers.KeyAt(i));
}
void
Server::LoginAll()
{
for (uint32 i = 0; i < fLoopers.CountItems(); i++) {
ProtocolLooper* looper = fLoopers.ValueAt(i);
BMessage* msg = new BMessage(IM_MESSAGE);
msg->AddInt32("im_what", IM_SET_OWN_STATUS);
2021-06-20 12:44:20 -05:00
msg->AddInt32("status", STATUS_ONLINE);
looper->PostMessage(msg);
}
}
filter_result
Server::Filter(BMessage* message, BHandler **target)
{
filter_result result = B_DISPATCH_MESSAGE;
2010-05-19 17:28:26 -05:00
switch (message->what) {
case IM_MESSAGE:
result = ImMessage(message);
break;
case IM_ERROR:
ImError(message);
break;
2021-06-20 12:44:20 -05:00
case APP_CLOSE_CHAT_WINDOW:
{
BString id = message->FindString("chat_id");
if (id.Length() > 0) {
bool found = false;
// Conversation* item = fChatMap.ValueFor(id, &found);
}
result = B_SKIP_MESSAGE;
break;
}
case APP_ACCOUNT_DISABLED:
{
BString name;
int64 instance;
if (message->FindInt64("instance", &instance) != B_OK)
return result;
// "Whoops" notification
if (AppPreferences::Item()->NotifyProtocolStatus == true
&& message->FindString("name", &name) == B_OK) {
BBitmap* icon = new BBitmap(message);
2021-07-19 09:54:27 -05:00
BString content(B_TRANSLATE("%user% has been disabled!"));
content.ReplaceAll("%user%", name);
2021-07-19 09:54:27 -05:00
_SendNotification(B_TRANSLATE("Disabled"), content, icon);
}
break;
}
2021-06-20 12:44:20 -05:00
case APP_REPLICANT_MESSENGER:
{
BMessenger* messenger = new BMessenger();
status_t ret = message->FindMessenger(
"messenger", messenger);
if (ret != B_OK || !messenger->IsValid()) {
printf("err %s\n", strerror(ret));
break;
}
AccountManager* accountManager = AccountManager::Get();
accountManager->SetReplicantMessenger(messenger);
accountManager->ReplicantStatusNotify(accountManager->Status());
break;
}
2021-06-20 12:44:20 -05:00
case APP_USER_INFO:
{
User* user = _EnsureUser(message);
if (user != NULL) {
UserInfoWindow* win = new UserInfoWindow(user);
win->Show();
}
break;
}
2021-06-20 12:44:20 -05:00
case APP_REQUEST_HELP:
2021-06-15 00:45:51 -05:00
{
BString body;
BString cmd_name = message->FindString("misc_str");
int64 instance = message->FindInt64("instance");
2021-06-15 00:45:51 -05:00
Conversation* chat = _EnsureConversation(message);
if (chat == NULL)
break;
if (cmd_name.IsEmpty() == false) {
ChatCommand* cmd = CommandById(cmd_name, instance);
2021-06-15 00:45:51 -05:00
if (cmd == NULL)
2021-07-19 09:54:27 -05:00
body = B_TRANSLATE("-- That command doesn't exist. Try "
"'/help' for a list.\n");
2021-06-15 00:45:51 -05:00
else {
body = "** ";
body << cmd->GetName() << "" << cmd->GetDesc() << "\n";
}
}
else {
CommandMap combinedCmds;
combinedCmds.AddList(fCommands);
combinedCmds.AddList(chat->GetProtocolLooper()->Commands());
2021-07-19 09:54:27 -05:00
body << B_TRANSLATE("** Commands: ");
for (int i = 0; i < combinedCmds.CountItems(); i++) {
ChatCommand* cmd = combinedCmds.ValueAt(i);
2021-06-15 00:45:51 -05:00
if (i > 0) body << ", ";
body << cmd->GetName();
}
body << "\n";
}
BMessage* help = new BMessage(IM_MESSAGE);
help->AddInt32("im_what", IM_MESSAGE_RECEIVED);
help->AddString("body", body);
help->AddInt64("when", 0);
chat->ImMessage(help);
break;
}
default:
// Dispatch not handled messages to main window
break;
}
return result;
}
filter_result
Server::ImMessage(BMessage* msg)
{
filter_result result = B_DISPATCH_MESSAGE;
int32 im_what = msg->FindInt32("im_what");
switch (im_what) {
case IM_CONTACT_LIST:
{
int i = 0;
BString id;
while (msg->FindString("user_id", i++, &id) == B_OK)
_EnsureContact(msg);
result = B_SKIP_MESSAGE;
break;
}
case IM_CONTACT_LIST_CONTACT_REMOVED:
{
Contact* contact = _EnsureContact(msg);
ProtocolLooper* looper = _LooperFromMessage(msg);
if (looper == NULL || contact == NULL) {
result = B_SKIP_MESSAGE;
break;
}
looper->RemoveContact(contact);
break;
}
case IM_OWN_STATUS_SET:
{
int32 status;
const char* protocol;
if (msg->FindInt32("status", &status) != B_OK)
return B_SKIP_MESSAGE;
if (msg->FindString("protocol", &protocol) != B_OK)
return B_SKIP_MESSAGE;
AccountManager* accountManager = AccountManager::Get();
2021-06-20 12:44:20 -05:00
accountManager->SetStatus((UserStatus)status);
break;
}
case IM_STATUS_SET:
{
int32 status;
if (msg->FindInt32("status", &status) != B_OK)
return B_SKIP_MESSAGE;
User* user = _EnsureUser(msg);
if (!user)
break;
2021-06-20 12:44:20 -05:00
user->SetNotifyStatus((UserStatus)status);
BString statusMsg;
if (msg->FindString("message", &statusMsg) == B_OK) {
user->SetNotifyPersonalStatus(statusMsg);
}
break;
}
case IM_OWN_CONTACT_INFO:
{
BString id = msg->FindString("user_id");
ProtocolLooper* looper = _LooperFromMessage(msg);
if (looper == NULL || id.IsEmpty() == true) break;
Contact* contact = looper->GetOwnContact();
if (contact == NULL) {
contact = new Contact(id, Looper());
contact->SetProtocolLooper(looper);
looper->SetOwnContact(contact);
}
BString name;
if (msg->FindString("user_name", &name) == B_OK)
contact->SetNotifyName(name);
break;
}
case IM_CONTACT_INFO:
{
Contact* contact = _EnsureContact(msg);
if (!contact)
break;
2010-05-19 12:11:22 -05:00
const char* name = NULL;
2021-06-07 11:45:30 -05:00
if ((msg->FindString("user_name", &name) == B_OK)
&& (strcmp(name, "") != 0))
contact->SetNotifyName(name);
BString status;
if (msg->FindString("message", &status) == B_OK)
contact->SetNotifyPersonalStatus(status);
break;
}
case IM_EXTENDED_CONTACT_INFO:
{
Contact* contact = _EnsureContact(msg);
if (!contact)
break;
if (contact->GetName().Length() > 0)
break;
const char* name = NULL;
2021-06-07 11:45:30 -05:00
if ((msg->FindString("full_name", &name) == B_OK)
&& (strcmp(name, "") != 0))
contact->SetNotifyName(name);
2021-06-07 11:45:30 -05:00
else if ((msg->FindString("user_name", &name) == B_OK)
&& (strcmp(name, "") != 0))
contact->SetNotifyName(name);
break;
}
case IM_OWN_AVATAR_SET:
{
ProtocolLooper* looper = _LooperFromMessage(msg);
Contact* contact = looper->GetOwnContact();
entry_ref ref;
if (msg->FindRef("ref", &ref) == B_OK) {
BBitmap* bitmap = BTranslationUtils::GetBitmap(&ref);
if (bitmap != NULL)
contact->SetNotifyAvatarBitmap(bitmap);
}
break;
}
case IM_AVATAR_SET:
{
User* user = _EnsureUser(msg);
if (!user)
break;
entry_ref ref;
if (msg->FindRef("ref", &ref) == B_OK) {
BBitmap* bitmap = BTranslationUtils::GetBitmap(&ref);
user->SetNotifyAvatarBitmap(bitmap);
} else
user->SetNotifyAvatarBitmap(NULL);
break;
}
case IM_CREATE_CHAT:
{
BString user_id = msg->FindString("user_id");
if (user_id.IsEmpty() == false) {
User* user = ContactById(user_id, msg->FindInt64("instance"));
user->GetProtocolLooper()->PostMessage(msg);
}
break;
}
case IM_CHAT_CREATED:
{
Conversation* chat = _EnsureConversation(msg);
User* user = _EnsureUser(msg);
if (chat != NULL && user != NULL) {
chat->AddUser(user);
chat->ShowView(false, true);
}
break;
}
case IM_JOIN_ROOM:
{
SendProtocolMessage(msg);
break;
}
2021-06-18 01:30:59 -05:00
case IM_ROOM_CREATED:
case IM_ROOM_JOINED:
{
Conversation* chat = _EnsureConversation(msg);
if (chat != NULL)
chat->ImMessage(msg);
break;
}
case IM_ROOM_PARTICIPANTS:
{
Conversation* chat = _EnsureConversation(msg);
BStringList ids;
BStringList name;
msg->FindStrings("user_name", &name);
if (msg->FindStrings("user_id", &ids) != B_OK)
break;
ProtocolLooper* protoLooper = _LooperFromMessage(msg);
for (int i = 0; i < ids.CountStrings(); i++) {
User* user = _EnsureUser(ids.StringAt(i), protoLooper);
if (name.CountStrings() >= i && !name.StringAt(i).IsEmpty())
user->SetNotifyName(name.StringAt(i));
chat->AddUser(user);
}
break;
}
case IM_ROOM_PARTICIPANT_JOINED:
case IM_ROOM_PARTICIPANT_LEFT:
case IM_ROOM_PARTICIPANT_BANNED:
case IM_ROOM_PARTICIPANT_KICKED:
{
Conversation* chat = _EnsureConversation(msg);
if (chat == NULL)
break;
chat->ImMessage(msg);
break;
}
case IM_ROOM_METADATA:
{
Conversation* chat = _EnsureConversation(msg);
if (chat != NULL)
chat->ImMessage(msg);
break;
}
2021-06-07 11:45:30 -05:00
case IM_ROOM_ROLECHANGED:
{
Conversation* chat = _EnsureConversation(msg);
BString user_id;
Role* role = _GetRole(msg);
if (chat == NULL || msg->FindString("user_id", &user_id) != B_OK
|| role == NULL)
break;
chat->SetRole(user_id, role);
break;
}
2021-06-07 11:45:30 -05:00
case IM_ROOM_NAME_SET:
{
BString name;
Conversation* chat = _EnsureConversation(msg);
if (msg->FindString("chat_name", &name) != B_OK || chat == NULL)
break;
chat->SetNotifyName(name.String());
break;
}
2021-06-07 11:45:30 -05:00
case IM_ROOM_SUBJECT_SET:
{
BString subject;
Conversation* chat = _EnsureConversation(msg);
if (msg->FindString("subject", &subject) != B_OK || chat == NULL)
break;
chat->SetNotifySubject(subject.String());
break;
}
case IM_SEND_MESSAGE:
{
// Route this message through the appropriate ProtocolLooper
Conversation* conversation = _EnsureConversation(msg);
if (conversation->GetProtocolLooper())
conversation->GetProtocolLooper()->PostMessage(msg);
break;
}
case IM_MESSAGE_SENT:
case IM_MESSAGE_RECEIVED:
{
Conversation* item = _EnsureConversation(msg);
item->ImMessage(msg);
break;
}
case IM_ROOM_INVITE_RECEIVED:
{
BString chat_id;
User* user = _EnsureUser(msg);
BString user_id = msg->FindString("user_id");
BString user_name = user_id;
BString chat_name = msg->FindString("chat_name");
BString body = msg->FindString("body");
ProtocolLooper* looper = _LooperFromMessage(msg);
if (msg->FindString("chat_id", &chat_id) != B_OK || looper == NULL)
{
result = B_SKIP_MESSAGE;
break;
}
if (chat_name.IsEmpty() == true)
chat_name = chat_id;
if (user != NULL)
user_name = user->GetName();
2021-07-19 09:54:27 -05:00
BString alertBody(B_TRANSLATE("You've been invited to %room%."));
if (user_id.IsEmpty() == false)
2021-07-19 09:54:27 -05:00
alertBody = B_TRANSLATE("%user% has invited you to %room%.");
if (body.IsEmpty() == false)
alertBody << "\n\n\"%body%\"";
alertBody.ReplaceAll("%user%", user_name);
alertBody.ReplaceAll("%room%", chat_name);
alertBody.ReplaceAll("%body%", body);
BMessage* accept = new BMessage(IM_MESSAGE);
accept->AddInt32("im_what", IM_ROOM_INVITE_ACCEPT);
accept->AddString("chat_id", chat_id);
BMessage* reject = new BMessage(IM_MESSAGE);
accept->AddInt32("im_what", IM_ROOM_INVITE_REFUSE);
reject->AddString("chat_id", chat_id);
InviteDialogue* invite = new InviteDialogue(BMessenger(looper),
2021-07-19 09:54:27 -05:00
B_TRANSLATE("Invitation received"),
alertBody.String(), accept, reject);
invite->Go();
break;
}
case IM_USER_STARTED_TYPING:
case IM_USER_STOPPED_TYPING:
{
// User* user = _EnsureUser();
// Conversation* chat = _EnsureConversation();
result = B_SKIP_MESSAGE;
break;
}
2010-05-30 07:17:32 -05:00
case IM_PROGRESS:
{
ProtocolLooper* looper = _LooperFromMessage(msg);
2010-05-30 07:17:32 -05:00
const char* protocol = NULL;
const char* title = NULL;
const char* message = NULL;
float progress = 0.0f;
if (looper == NULL)
2010-05-30 07:17:32 -05:00
return result;
if (msg->FindString("title", &title) != B_OK)
return result;
if (msg->FindString("message", &message) != B_OK)
return result;
if (msg->FindFloat("progress", &progress) != B_OK)
return result;
2021-06-20 12:44:20 -05:00
if (!AppPreferences::Item()->NotifyProtocolStatus)
break;
2010-05-30 07:17:32 -05:00
BNotification notification(B_PROGRESS_NOTIFICATION);
2021-06-22 01:06:00 -05:00
notification.SetGroup(BString(APP_NAME));
2010-05-30 07:17:32 -05:00
notification.SetTitle(title);
notification.SetIcon(looper->Protocol()->Icon());
2010-05-30 07:17:32 -05:00
notification.SetContent(message);
notification.SetProgress(progress);
notification.Send();
2010-05-30 07:17:32 -05:00
break;
}
case IM_NOTIFICATION: {
_ProtocolNotification(_LooperFromMessage(msg),
msg->FindString("title"), msg->FindString("message"),
(notification_type)msg->GetInt32("type",
B_INFORMATION_NOTIFICATION));
break;
}
case IM_PROTOCOL_RELOAD_COMMANDS:
{
ProtocolLooper* looper = _LooperFromMessage(msg);
if (looper == NULL) break;
looper->LoadCommands();
break;
}
case IM_PROTOCOL_READY:
{
ProtocolLooper* looper = _LooperFromMessage(msg);
if (looper == NULL) break;
// Ready notification
if (AppPreferences::Item()->NotifyProtocolStatus == true)
2021-07-19 09:54:27 -05:00
_ProtocolNotification(looper, BString(B_TRANSLATE("Connected")),
BString(B_TRANSLATE("%user% has connected!")));
// Join cached rooms
BEntry entry;
char fileName[B_FILE_NAME_LENGTH] = {'\0'};
BDirectory dir(RoomsCachePath(looper->Protocol()->GetName()));
while (dir.GetNextEntry(&entry, true) == B_OK)
if (entry.GetName(fileName) == B_OK) {
int32 flags;
BFile file(&entry, B_READ_ONLY);
if (file.InitCheck() != B_OK)
continue;
2021-06-20 12:44:20 -05:00
if (file.ReadAttr("Chat:flags", B_INT32_TYPE, 0, &flags,
sizeof(int32)) < 0)
continue;
if (!(flags & ROOM_AUTOJOIN) && !(flags & ROOM_AUTOCREATE))
continue;
BMessage join(IM_MESSAGE);
int32 im_what = IM_JOIN_ROOM;
if (flags & ROOM_AUTOCREATE) {
im_what = IM_CREATE_CHAT;
join.AddString("user_id", fileName);
}
join.AddInt32("im_what", im_what);
join.AddString("chat_id", fileName);
looper->PostMessage(&join);
}
break;
}
case IM_PROTOCOL_DISABLE:
{
int64 instance = 0;
if (msg->FindInt64("instance", &instance) != B_OK) {
result = B_SKIP_MESSAGE;
break;
}
RemoveProtocolLooper(instance);
break;
}
default:
break;
}
return result;
}
void
Server::ImError(BMessage* msg)
{
const char* error = NULL;
const char* detail = msg->FindString("detail");
ProtocolLooper* looper = _LooperFromMessage(msg);
if (msg->FindString("error", &error) != B_OK || looper == NULL)
return;
// Format error message
BString errMsg(looper->Protocol()->GetName());
errMsg << "" << error;
if (detail)
errMsg << "\n\n" << detail;
2021-07-19 09:54:27 -05:00
BAlert* alert = new BAlert(B_TRANSLATE("Error"), errMsg.String(),
B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->Go();
}
void
2021-06-20 12:44:20 -05:00
Server::AddProtocolLooper(bigtime_t instanceId, ChatProtocol* cayap)
{
ProtocolLooper* looper = new ProtocolLooper(cayap, instanceId);
fLoopers.AddItem(instanceId, looper);
fAccounts.AddItem(cayap->GetName(), instanceId);
}
void
Server::RemoveProtocolLooper(bigtime_t instanceId)
{
ProtocolLooper* looper = GetProtocolLooper(instanceId);
if (looper == NULL)
return;
ChatMap chats = looper->Conversations();
for (int i = 0; i < chats.CountItems(); i++)
delete chats.ValueAt(i);
UserMap users = looper->Users();
for (int i = 0; i < users.CountItems(); i++)
delete users.ValueAt(i);
fLoopers.RemoveItemFor(instanceId);
fAccounts.RemoveItemFor(looper->Protocol()->GetName());
looper->Lock();
looper->Quit();
}
ProtocolLooper*
Server::GetProtocolLooper(bigtime_t instanceId)
{
bool found = false;
return fLoopers.ValueFor(instanceId, &found);
}
AccountInstances
Server::GetAccounts()
{
return fAccounts;
}
void
Server::SendProtocolMessage(BMessage* msg)
{
// Skip null messages
if (!msg)
return;
// Check if message contains the instance field
bigtime_t id;
if (msg->FindInt64("instance", &id) == B_OK) {
bool found = false;
ProtocolLooper* looper
= fLoopers.ValueFor(id, &found);
if (found)
looper->PostMessage(msg);
}
}
void
Server::SendAllProtocolMessage(BMessage* msg)
{
// Skip null messages
if (!msg)
return;
// Send message to all protocols
for (uint32 i = 0; i < fLoopers.CountItems(); i++) {
ProtocolLooper* looper = fLoopers.ValueAt(i);
looper->PostMessage(msg);
}
}
RosterMap
Server::Contacts() const
{
RosterMap contacts;
for (int i = 0; i < fAccounts.CountItems(); i++) {
ProtocolLooper* fruitLoop = fLoopers.ValueFor(fAccounts.ValueAt(i));
if (fruitLoop == NULL) continue;
contacts.AddList(fruitLoop->Contacts());
}
return contacts;
}
2021-05-23 14:39:07 -05:00
Contact*
Server::ContactById(BString id, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
Contact* result = NULL;
if (looper != NULL)
result = looper->ContactById(id);
return result;
}
void
Server::AddContact(Contact* contact, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
if (looper != NULL)
looper->AddContact(contact);
}
UserMap
Server::Users() const
{
UserMap users;
for (int i = 0; i < fAccounts.CountItems(); i++) {
ProtocolLooper* fruitLoop = fLoopers.ValueFor(fAccounts.ValueAt(i));
if (fruitLoop == NULL) continue;
users.AddList(fruitLoop->Users());
}
return users;
}
User*
Server::UserById(BString id, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
User* result = NULL;
if (looper != NULL)
result = looper->UserById(id);
return result;
}
void
Server::AddUser(User* user, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
if (looper != NULL)
looper->AddUser(user);
}
ChatMap
Server::Conversations() const
{
ChatMap chats;
for (int i = 0; i < fAccounts.CountItems(); i++) {
ProtocolLooper* fruitLoop = fLoopers.ValueFor(fAccounts.ValueAt(i));
if (fruitLoop == NULL) continue;
chats.AddList(fruitLoop->Conversations());
}
return chats;
}
Conversation*
Server::ConversationById(BString id, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
Conversation* result = NULL;
if (looper != NULL)
result = looper->ConversationById(id);
return result;
}
void
Server::AddConversation(Conversation* chat, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
if (looper != NULL)
looper->AddConversation(chat);
}
ChatCommand*
Server::CommandById(BString id, int64 instance)
{
ProtocolLooper* looper = fLoopers.ValueFor(instance);
ChatCommand* result = NULL;
if (looper != NULL)
result = looper->CommandById(id);
if (result == NULL)
result = fCommands.ValueFor(id);
return result;
}
BObjectList<BMessage>
2021-06-16 04:33:06 -05:00
Server::ChatPopUpItems()
{
return fChatItems;
}
BObjectList<BMessage>
Server::UserPopUpItems()
{
return fUserItems;
}
ProtocolLooper*
Server::_LooperFromMessage(BMessage* message)
{
if (!message)
return NULL;
bigtime_t identifier;
if (message->FindInt64("instance", &identifier) == B_OK) {
bool found = false;
ProtocolLooper* looper = fLoopers.ValueFor(identifier, &found);
if (found)
return looper;
}
return NULL;
}
2021-05-23 14:39:07 -05:00
Contact*
Server::_EnsureContact(BMessage* message)
{
BString id = message->FindString("user_id");
ProtocolLooper* looper = _LooperFromMessage(message);
if (looper == NULL) return NULL;
Contact* contact = looper->ContactById(id);
if (contact == NULL && id.IsEmpty() == false && looper != NULL) {
contact = new Contact(id, Looper());
contact->SetProtocolLooper(looper);
looper->AddContact(contact);
}
return contact;
}
User*
Server::_EnsureUser(BMessage* message)
{
BString id = message->FindString("user_id");
return _EnsureUser(id, _LooperFromMessage(message));
}
User*
Server::_EnsureUser(BString id, ProtocolLooper* protoLooper)
{
User* user = protoLooper->UserById(id);
if (user == NULL && id.IsEmpty() == false) {
user = new User(id, Looper());
user->SetProtocolLooper(protoLooper);
protoLooper->AddUser(user);
}
return user;
}
Conversation*
Server::_EnsureConversation(BMessage* message)
{
ProtocolLooper* looper;
if (!message || (looper = _LooperFromMessage(message)) == NULL)
return NULL;
BString chat_id = message->FindString("chat_id");
Conversation* item = NULL;
if (chat_id.IsEmpty() == false) {
item = looper->ConversationById(chat_id);
if (item == NULL) {
item = new Conversation(chat_id, Looper());
item->SetProtocolLooper(looper);
item->AddUser(looper->GetOwnContact());
looper->AddConversation(item);
BMessage meta(IM_MESSAGE);
meta.AddInt32("im_what", IM_GET_ROOM_METADATA);
meta.AddString("chat_id", chat_id);
BMessage users(IM_MESSAGE);
users.AddInt32("im_what", IM_GET_ROOM_PARTICIPANTS);
users.AddString("chat_id", chat_id);
looper->MessageReceived(&meta);
looper->MessageReceived(&users);
}
}
return item;
}
2021-05-23 14:39:07 -05:00
Role*
Server::_GetRole(BMessage* msg)
{
if (!msg)
return NULL;
BString title;
int32 perms;
int32 priority;
if (msg->FindString("role_title", &title) != B_OK
|| msg->FindInt32("role_perms", &perms) != B_OK
|| msg->FindInt32("role_priority", &priority) != B_OK)
return NULL;
return new Role(title, perms, priority);
}
void
Server::_ProtocolNotification(ProtocolLooper* looper, BString title,
BString desc, notification_type type)
{
if (looper == NULL || title.IsEmpty() == true) return;
title.ReplaceAll("%user%", looper->Protocol()->GetName());
desc.ReplaceAll("%user%", looper->Protocol()->GetName());
_SendNotification(title, desc, looper->Protocol()->Icon(), type);
}
void
Server::_SendNotification(BString title, BString content, BBitmap* icon,
notification_type type)
{
BNotification notification(type);
notification.SetGroup(BString(APP_NAME));
notification.SetTitle(title);
if (content.IsEmpty() == false)
notification.SetContent(content);
if (icon != NULL)
notification.SetIcon(icon);
notification.Send();
}