2021-06-23 23:57:27 -05:00
|
|
|
|
/*
|
|
|
|
|
* Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
|
|
|
|
|
* Copyright 1998-2021, Pidgin/Finch/libpurple contributors
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2021-06-24 12:22:34 -05:00
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
|
* 02110-1301, USA.
|
2021-06-23 23:57:27 -05:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "PurpleApp.h"
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#include <libintl.h>
|
2021-06-27 20:42:37 -05:00
|
|
|
|
#include <libpurple/status.h>
|
2021-06-23 23:57:27 -05:00
|
|
|
|
|
2021-07-12 10:09:29 -05:00
|
|
|
|
#include <Alert.h>
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#include <Catalog.h>
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
#include <Directory.h>
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#include <Locale.h>
|
2021-06-27 16:46:38 -05:00
|
|
|
|
#include <MessageRunner.h>
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
#include <Path.h>
|
2021-06-27 17:33:09 -05:00
|
|
|
|
#include <Roster.h>
|
2021-06-27 16:46:38 -05:00
|
|
|
|
|
2021-06-27 17:33:09 -05:00
|
|
|
|
#include <Cardie.h>
|
2021-06-27 16:46:38 -05:00
|
|
|
|
#include <ChatProtocolMessages.h>
|
2021-07-03 15:00:05 -05:00
|
|
|
|
#include <Flags.h>
|
2021-06-27 16:46:38 -05:00
|
|
|
|
|
|
|
|
|
#include "Purple.h"
|
2021-07-11 15:22:49 -05:00
|
|
|
|
#include "PurpleDialog.h"
|
2021-06-27 16:46:38 -05:00
|
|
|
|
#include "PurpleMessages.h"
|
|
|
|
|
|
2021-06-23 23:57:27 -05:00
|
|
|
|
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp"
|
|
|
|
|
|
|
|
|
|
|
2021-06-23 23:57:27 -05:00
|
|
|
|
int
|
|
|
|
|
main(int arc, char** argv)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
|
2021-06-23 23:57:27 -05:00
|
|
|
|
PurpleApp app;
|
|
|
|
|
app.Run();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PurpleApp::PurpleApp()
|
|
|
|
|
:
|
2021-06-27 16:46:38 -05:00
|
|
|
|
BApplication(PURPLE_SIGNATURE),
|
|
|
|
|
fGloop(g_main_loop_new(NULL, false))
|
2021-06-23 23:57:27 -05:00
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
init_gettext();
|
2021-06-23 23:57:27 -05:00
|
|
|
|
if (init_libpurple() != B_OK)
|
|
|
|
|
std::cerr << "libpurple initialization failed. Please report!\n";
|
|
|
|
|
|
|
|
|
|
_GetProtocolsInfo();
|
2021-06-27 17:33:09 -05:00
|
|
|
|
new BMessageRunner(this, new BMessage(G_MAIN_LOOP), 100000, -1);
|
2021-06-29 20:02:45 -05:00
|
|
|
|
new BMessageRunner(this, new BMessage(CHECK_APP), 10000000, -1);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PurpleApp::MessageReceived(BMessage* msg)
|
|
|
|
|
{
|
|
|
|
|
switch (msg->what)
|
|
|
|
|
{
|
2021-06-27 20:42:37 -05:00
|
|
|
|
case IM_MESSAGE:
|
|
|
|
|
ImMessage(msg);
|
|
|
|
|
break;
|
2021-06-23 23:57:27 -05:00
|
|
|
|
case PURPLE_REQUEST_PROTOCOL_COUNT:
|
|
|
|
|
{
|
2021-06-27 16:46:38 -05:00
|
|
|
|
int64 thread_id;
|
2021-06-26 20:40:39 -05:00
|
|
|
|
if (msg->FindInt64("thread_id", &thread_id) != B_OK) return;
|
2021-06-23 23:57:27 -05:00
|
|
|
|
send_data(thread_id, fProtocols.CountItems(), NULL, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case PURPLE_REQUEST_PROTOCOL_INFO:
|
|
|
|
|
{
|
2021-06-27 16:46:38 -05:00
|
|
|
|
int64 thread_id;
|
2021-06-26 20:40:39 -05:00
|
|
|
|
if (msg->FindInt64("thread_id", &thread_id) != B_OK) return;
|
2021-07-02 10:24:34 -05:00
|
|
|
|
int32 index = msg->GetInt32("index", 0);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
ProtocolInfo* info = fProtocols.ItemAt(index);
|
|
|
|
|
|
2021-07-04 11:31:32 -05:00
|
|
|
|
BMessage protoInfo;
|
|
|
|
|
BMessage temps;
|
|
|
|
|
temps.AddMessage("account", new BMessage(info->accountTemplate));
|
|
|
|
|
temps.AddMessage("room", new BMessage(info->roomTemplate));
|
|
|
|
|
protoInfo.AddMessage("templates", &temps);
|
|
|
|
|
protoInfo.AddString("name", info->name);
|
|
|
|
|
protoInfo.AddString("id", info->id);
|
2021-07-07 15:02:59 -05:00
|
|
|
|
protoInfo.AddString("icon", info->iconName);
|
2021-07-04 11:31:32 -05:00
|
|
|
|
|
|
|
|
|
SendMessage(thread_id, protoInfo);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-27 17:33:09 -05:00
|
|
|
|
case PURPLE_CONNECT_ACCOUNT:
|
2021-06-26 20:40:39 -05:00
|
|
|
|
{
|
2021-07-04 11:31:32 -05:00
|
|
|
|
_ParseAccountTemplate(msg);
|
2021-06-26 20:40:39 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-27 16:46:38 -05:00
|
|
|
|
case PURPLE_REGISTER_THREAD:
|
|
|
|
|
{
|
|
|
|
|
BString accName = msg->FindString("account_name");
|
|
|
|
|
BString username = fAccounts.ValueFor(accName);
|
|
|
|
|
int64 thread;
|
|
|
|
|
if (username.IsEmpty() == true
|
|
|
|
|
|| msg->FindInt64("thread_id", &thread) != B_OK)
|
|
|
|
|
break;
|
|
|
|
|
fAccountThreads.AddItem(username, thread);
|
2021-07-05 23:56:59 -05:00
|
|
|
|
|
|
|
|
|
SendMessage(thread, _GetCommands(_AccountFromMessage(msg)));
|
2021-06-27 16:46:38 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
Redesign add-on disconnection
Currently, add-ons are disconnected when ChatProtocol::Shutdown() is
called, which the add-on can do by itself― but there is no standard way
for add-ons to notify the app about their Shutdown. Because of this,
they tend to not call Shutdown()― instead (as in the case of the Jabber
add-on), they display a BAlert (IM_ERROR) notifying the user of the
connection error, but the account is considered active by Cardie (and
its threads are still existant, including its ProtocolLooper).
Zombies are bad, so this is redesigned somewhat with this commit:
Protocols should no longer call ChatProtocol::Shutdown() themselves,
they must send an IM_MESSAGE of IM_PROTOCOL_DISABLE to the app.
This will delete its ProtocolLooper, which in turn will send a
notification to the user and delete the ChatProtocol, and so
calling ChatProtocol::Shutdown().
In the included protocols, an IM_ERROR is sent right before
IM_PROTOCOL_DISABLE is sent if due to a connection error. This is not
required, but it is courteous to inform your user about the "why." :)
2021-07-18 17:52:36 -05:00
|
|
|
|
case PURPLE_DISCONNECT_ACCOUNT:
|
2021-06-27 17:33:09 -05:00
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
if (account == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
BString account_name = msg->FindString("account_name");
|
|
|
|
|
const char* username = purple_account_get_username(account);
|
|
|
|
|
fAccountThreads.RemoveItemFor(BString(username));
|
|
|
|
|
fAccounts.RemoveItemFor(account_name);
|
|
|
|
|
|
|
|
|
|
purple_account_disconnect(account);
|
|
|
|
|
|
|
|
|
|
if (fAccountThreads.CountItems() == 0 || fAccounts.CountItems() == 0)
|
|
|
|
|
Quit();
|
|
|
|
|
}
|
|
|
|
|
case CHECK_APP:
|
|
|
|
|
{
|
|
|
|
|
BRoster roster;
|
|
|
|
|
if (roster.IsRunning(APP_SIGNATURE) == false)
|
|
|
|
|
Quit();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-27 16:46:38 -05:00
|
|
|
|
case G_MAIN_LOOP:
|
|
|
|
|
g_main_context_iteration(g_main_loop_get_context(fGloop), false);
|
|
|
|
|
break;
|
2021-06-23 23:57:27 -05:00
|
|
|
|
default:
|
2021-06-24 12:22:34 -05:00
|
|
|
|
BApplication::MessageReceived(msg);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 20:42:37 -05:00
|
|
|
|
void
|
|
|
|
|
PurpleApp::ImMessage(BMessage* msg)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― Room moderation"
|
2021-06-27 20:42:37 -05:00
|
|
|
|
switch (msg->FindInt32("im_what"))
|
|
|
|
|
{
|
|
|
|
|
case IM_SET_OWN_STATUS:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
UserStatus status = (UserStatus)msg->FindInt32("status");
|
|
|
|
|
PurpleStatusPrimitive prim = cardie_status_to_purple(status);
|
|
|
|
|
const char* primId = purple_primitive_get_id_from_type(prim);
|
|
|
|
|
|
|
|
|
|
std::cout << "setting status to " << primId << "…\n";
|
|
|
|
|
purple_account_set_status(account, primId, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-28 12:51:50 -05:00
|
|
|
|
case IM_SEND_MESSAGE:
|
|
|
|
|
{
|
|
|
|
|
BString body;
|
2021-07-03 15:00:05 -05:00
|
|
|
|
if (msg->FindString("body", &body) != B_OK) break;
|
2021-06-28 12:51:50 -05:00
|
|
|
|
|
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
|
|
|
|
PurpleConvIm* im = purple_conversation_get_im_data(conv);
|
|
|
|
|
|
|
|
|
|
if (chat != NULL)
|
|
|
|
|
purple_conv_chat_send(chat, body.String());
|
|
|
|
|
else if (im != NULL)
|
|
|
|
|
purple_conv_im_send(im, body.String());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-03 15:01:32 -05:00
|
|
|
|
case IM_CREATE_CHAT:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
const char* user_id = msg->FindString("user_id");
|
|
|
|
|
if (user_id == NULL || purple_find_buddy(account, user_id) == NULL)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
purple_conversation_new(PURPLE_CONV_TYPE_IM, account, user_id);
|
|
|
|
|
|
|
|
|
|
BMessage created(IM_MESSAGE);
|
|
|
|
|
created.AddInt32("im_what", IM_CHAT_CREATED);
|
|
|
|
|
created.AddString("user_id", user_id);
|
|
|
|
|
created.AddString("chat_id", user_id);
|
|
|
|
|
SendMessage(account, created);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-05 12:42:20 -05:00
|
|
|
|
case IM_CREATE_ROOM:
|
|
|
|
|
{
|
|
|
|
|
serv_join_chat(_ConnectionFromMessage(msg), _ParseRoomTemplate(msg));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-01 20:52:46 -05:00
|
|
|
|
case IM_JOIN_ROOM:
|
|
|
|
|
{
|
2021-07-05 13:40:59 -05:00
|
|
|
|
serv_join_chat(_ConnectionFromMessage(msg), _ParseRoomTemplate(msg));
|
2021-07-01 20:52:46 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_LEAVE_ROOM:
|
|
|
|
|
{
|
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
if (conv == NULL || chat_id.IsEmpty() == true) break;
|
|
|
|
|
|
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
|
|
|
|
if (chat != NULL)
|
|
|
|
|
serv_chat_leave(purple_conversation_get_gc(conv),
|
|
|
|
|
purple_conv_chat_get_id(chat));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-29 15:20:27 -05:00
|
|
|
|
case IM_GET_ROOM_METADATA:
|
|
|
|
|
{
|
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
|
|
|
|
|
|
|
|
|
BMessage meta(IM_MESSAGE);
|
|
|
|
|
meta.AddInt32("im_what", IM_ROOM_METADATA);
|
|
|
|
|
meta.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
meta.AddString("chat_name", purple_conversation_get_title(conv));
|
2021-07-03 15:01:32 -05:00
|
|
|
|
meta.AddInt32("room_default_flags",
|
|
|
|
|
0 | ROOM_LOG_LOCALLY | ROOM_POPULATE_LOGS);
|
2021-06-29 15:20:27 -05:00
|
|
|
|
if (chat != NULL)
|
|
|
|
|
meta.AddString("subject", purple_conv_chat_get_topic(chat));
|
|
|
|
|
SendMessage(purple_conversation_get_account(conv), meta);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_GET_ROOM_PARTICIPANTS:
|
|
|
|
|
{
|
2021-07-07 20:44:11 -05:00
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
2021-06-29 15:20:27 -05:00
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
2021-06-29 20:02:45 -05:00
|
|
|
|
PurpleConvIm* im = purple_conversation_get_im_data(conv);
|
2021-07-03 15:00:05 -05:00
|
|
|
|
if (chat == NULL && im == NULL) break;
|
2021-06-29 15:20:27 -05:00
|
|
|
|
|
|
|
|
|
BStringList user_ids;
|
2021-06-29 20:02:45 -05:00
|
|
|
|
if (im != NULL)
|
|
|
|
|
user_ids.Add(BString(purple_conversation_get_name(conv)));
|
|
|
|
|
else {
|
|
|
|
|
GList* users = purple_conv_chat_get_users(chat);
|
|
|
|
|
for (int i = 0; users != NULL; users = users->next) {
|
|
|
|
|
PurpleConvChatBuddy* user = (PurpleConvChatBuddy*)users->data;
|
2021-07-07 20:44:11 -05:00
|
|
|
|
const char* user_name = purple_conv_chat_cb_get_name(user);
|
|
|
|
|
if (is_own_user(account, user_name) == false)
|
|
|
|
|
user_ids.Add(BString(user_name));
|
2021-06-29 20:02:45 -05:00
|
|
|
|
}
|
2021-06-29 15:20:27 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMessage parts(IM_MESSAGE);
|
|
|
|
|
parts.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
|
|
|
|
parts.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
parts.AddStrings("user_id", user_ids);
|
|
|
|
|
SendMessage(purple_conversation_get_account(conv), parts);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-01 18:34:56 -05:00
|
|
|
|
case IM_GET_CONTACT_LIST:
|
|
|
|
|
{
|
2021-07-03 15:00:05 -05:00
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
|
2021-07-01 18:34:56 -05:00
|
|
|
|
BStringList user_ids;
|
|
|
|
|
GSList* buddies = purple_blist_get_buddies();
|
|
|
|
|
for (int i = 0; buddies != NULL; buddies = buddies->next) {
|
|
|
|
|
PurpleBuddy* buddy = (PurpleBuddy*)buddies->data;
|
2021-07-03 15:00:05 -05:00
|
|
|
|
if (purple_buddy_get_account(buddy) == account)
|
|
|
|
|
user_ids.Add(BString(purple_buddy_get_name(buddy)));
|
2021-07-01 18:34:56 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMessage roster(IM_MESSAGE);
|
|
|
|
|
roster.AddInt32("im_what", IM_CONTACT_LIST);
|
|
|
|
|
roster.AddStrings("user_id", user_ids);
|
|
|
|
|
SendMessage(_AccountFromMessage(msg), roster);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-03 15:00:05 -05:00
|
|
|
|
case IM_CONTACT_LIST_ADD_CONTACT:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
const char* user_name = msg->FindString("user_name");
|
|
|
|
|
if (user_id.IsEmpty() == true || account == NULL) break;
|
|
|
|
|
|
|
|
|
|
PurpleBuddy* buddy =
|
|
|
|
|
purple_buddy_new(account, user_id.String(), user_name);
|
|
|
|
|
|
2021-07-05 17:48:32 -05:00
|
|
|
|
purple_blist_add_buddy(buddy, NULL, NULL, NULL);
|
2021-07-03 15:00:05 -05:00
|
|
|
|
purple_account_add_buddy_with_invite(account, buddy, NULL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_CONTACT_LIST_REMOVE_CONTACT:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
if (user_id.IsEmpty() == true || account == NULL) break;
|
|
|
|
|
|
|
|
|
|
PurpleBuddy* buddy = purple_find_buddy(account, user_id.String());
|
|
|
|
|
if (buddy == NULL) return;
|
|
|
|
|
purple_blist_remove_buddy(buddy);
|
|
|
|
|
purple_account_remove_buddy(account, buddy, NULL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-05 17:48:32 -05:00
|
|
|
|
case IM_CONTACT_LIST_EDIT_CONTACT:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
BString user_name = msg->FindString("user_name");
|
|
|
|
|
PurpleBuddy* buddy = purple_find_buddy(account, user_id.String());
|
|
|
|
|
if (buddy == NULL) return;
|
|
|
|
|
|
|
|
|
|
if (user_name.IsEmpty() == false)
|
|
|
|
|
purple_blist_alias_buddy(buddy, user_name.String());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-03 15:00:05 -05:00
|
|
|
|
case IM_GET_EXTENDED_CONTACT_INFO:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString user_id = msg->FindString("user_id");
|
|
|
|
|
if (user_id.IsEmpty() == true || account == NULL) break;
|
|
|
|
|
|
|
|
|
|
PurpleBuddy* buddy = purple_find_buddy(account, user_id.String());
|
|
|
|
|
if (buddy == NULL) return;
|
|
|
|
|
|
|
|
|
|
BString user_name = purple_buddy_get_alias(buddy);
|
|
|
|
|
if (user_name.IsEmpty() == true)
|
|
|
|
|
user_name = purple_buddy_get_server_alias(buddy);
|
|
|
|
|
|
|
|
|
|
BMessage info(IM_MESSAGE);
|
|
|
|
|
info.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO);
|
|
|
|
|
info.AddString("user_id", user_id);
|
|
|
|
|
if (user_name.IsEmpty() == false)
|
|
|
|
|
info.AddString("user_name", user_name);
|
|
|
|
|
SendMessage(account, info);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-01 20:18:10 -05:00
|
|
|
|
case IM_ROOM_SEND_INVITE:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
|
|
|
|
BString user_id = msg->FindString("user");
|
|
|
|
|
BString body = msg->FindString("body");
|
|
|
|
|
|
|
|
|
|
if (chat == NULL || user_id.IsEmpty() == true)
|
|
|
|
|
break;
|
|
|
|
|
if (body.IsEmpty() == true)
|
|
|
|
|
body = "(Invite)";
|
|
|
|
|
|
|
|
|
|
purple_conv_chat_invite_user(chat, user_id.String(), body.String(),
|
|
|
|
|
false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-01 19:49:39 -05:00
|
|
|
|
case IM_ROOM_INVITE_ACCEPT:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString key(purple_account_get_username(account));
|
|
|
|
|
key = key.Append("-invite-").Append(msg->FindString("chat_id"));
|
|
|
|
|
GHashTable* data = fInviteList.ValueFor(key);
|
|
|
|
|
|
|
|
|
|
if (data != NULL)
|
|
|
|
|
serv_join_chat(purple_account_get_connection(account), data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_INVITE_REFUSE:
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString key(purple_account_get_username(account));
|
|
|
|
|
key = key.Append("-invite-").Append(msg->FindString("chat_id"));
|
|
|
|
|
GHashTable* data = fInviteList.ValueFor(key);
|
|
|
|
|
|
|
|
|
|
if (data != NULL)
|
|
|
|
|
serv_reject_chat(purple_account_get_connection(account), data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-06 14:13:10 -05:00
|
|
|
|
case IM_ROOM_KICK_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** This protocol doesn't support kicking. "
|
|
|
|
|
"Send them a strongly worded e-mail.\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_BAN_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** Banning won't work with this protocol. "
|
|
|
|
|
"Try being mean instead.\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_UNBAN_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** You can't undo what was once done… "
|
|
|
|
|
"at least with this protocol.\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_MUTE_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** This protocol left the duct-tape at home― "
|
|
|
|
|
"we have nothing to put over their mouth!\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_UNMUTE_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** This protocol can't exactly unmute a user, "
|
|
|
|
|
"let alone make an omlett.\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_DEAFEN_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** This protocol doesn't support deafening, "
|
|
|
|
|
"but spamming the chat should be a good substitute. :^)\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IM_ROOM_UNDEAFEN_PARTICIPANT:
|
|
|
|
|
{
|
|
|
|
|
_SendSysText(_ConversationFromMessage(msg),
|
2021-07-18 21:51:38 -05:00
|
|
|
|
B_TRANSLATE("** This protocol is particularly self-concious,"
|
|
|
|
|
" and prefers that this person not see its chats.\n"));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
2021-07-06 01:22:08 -05:00
|
|
|
|
case PURPLE_CHAT_COMMAND:
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― Command errors"
|
2021-07-06 01:22:08 -05:00
|
|
|
|
PurpleConversation* conv = _ConversationFromMessage(msg);
|
|
|
|
|
BString cmd;
|
|
|
|
|
if (conv == NULL || msg->FindString("cmd_name", &cmd) != B_OK)
|
|
|
|
|
break;
|
|
|
|
|
cmd << " " << msg->FindString("misc_str");
|
|
|
|
|
|
|
|
|
|
const char* cmdline = cmd.String();
|
|
|
|
|
const char* escape = g_markup_escape_text(cmd, -1);
|
|
|
|
|
|
|
|
|
|
char* error = NULL;
|
|
|
|
|
PurpleCmdStatus status =
|
|
|
|
|
purple_cmd_do_command(conv, cmdline, escape, &error);
|
|
|
|
|
|
|
|
|
|
BMessage errorMsg(IM_MESSAGE);
|
|
|
|
|
errorMsg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
errorMsg.AddString("chat_id", msg->FindString("chat_id"));
|
|
|
|
|
BString errorBody;
|
|
|
|
|
|
|
|
|
|
switch (status)
|
|
|
|
|
{
|
|
|
|
|
case PURPLE_CMD_STATUS_FAILED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody = B_TRANSLATE("** Command failed %err%\n");
|
2021-07-06 01:22:08 -05:00
|
|
|
|
break;
|
|
|
|
|
case PURPLE_CMD_STATUS_NOT_FOUND:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody = B_TRANSLATE("** Command not found %err%\n");
|
2021-07-06 01:22:08 -05:00
|
|
|
|
break;
|
|
|
|
|
case PURPLE_CMD_STATUS_WRONG_ARGS:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody = B_TRANSLATE("** Invalid arguments to command %err%\n");
|
2021-07-06 01:22:08 -05:00
|
|
|
|
break;
|
|
|
|
|
case PURPLE_CMD_STATUS_WRONG_PRPL:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody = B_TRANSLATE("** Command isn't useful in this chat %err%\n");
|
2021-07-06 01:22:08 -05:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody = B_TRANSLATE("** Command error %err%\n");
|
2021-07-06 01:22:08 -05:00
|
|
|
|
}
|
|
|
|
|
if (status != PURPLE_CMD_STATUS_OK) {
|
2021-07-18 21:51:38 -05:00
|
|
|
|
errorBody.ReplaceAll("%err%", _tr(error));
|
2021-07-06 14:13:10 -05:00
|
|
|
|
_SendSysText(conv, errorBody.String());
|
2021-07-06 01:22:08 -05:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-27 20:42:37 -05:00
|
|
|
|
default:
|
2021-06-28 12:51:50 -05:00
|
|
|
|
std::cout << "IM_MESSAGE unhandled by Purple:\n";
|
2021-06-27 20:42:37 -05:00
|
|
|
|
msg->PrintToStream();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 16:46:38 -05:00
|
|
|
|
void
|
|
|
|
|
PurpleApp::SendMessage(thread_id thread, BMessage msg)
|
|
|
|
|
{
|
|
|
|
|
ssize_t size = msg.FlattenedSize();
|
|
|
|
|
char buffer[size];
|
|
|
|
|
|
|
|
|
|
send_data(thread, size, NULL, 0);
|
|
|
|
|
msg.Flatten(buffer, size);
|
|
|
|
|
send_data(thread, 0, buffer, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PurpleApp::SendMessage(PurpleAccount* account, BMessage msg)
|
|
|
|
|
{
|
|
|
|
|
const char* username = purple_account_get_username(account);
|
|
|
|
|
thread_id thread = fAccountThreads.ValueFor(BString(username));
|
|
|
|
|
if (thread > 0)
|
|
|
|
|
SendMessage(thread, msg);
|
|
|
|
|
else
|
|
|
|
|
std::cerr << "Failed to send message: " << msg.what << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-06 14:13:10 -05:00
|
|
|
|
void
|
|
|
|
|
PurpleApp::_SendSysText(PurpleConversation* conv, const char* body)
|
|
|
|
|
{
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
|
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
msg.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
msg.AddString("body", body);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_conversation_get_account(conv), msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-23 23:57:27 -05:00
|
|
|
|
void
|
|
|
|
|
PurpleApp::_GetProtocolsInfo()
|
|
|
|
|
{
|
|
|
|
|
GList* listIter = purple_plugins_get_protocols();
|
|
|
|
|
for (int i = 0; listIter; listIter = listIter->next) {
|
|
|
|
|
PurplePlugin* plugin = (PurplePlugin*)listIter->data;
|
2021-06-24 12:22:34 -05:00
|
|
|
|
if (plugin)
|
|
|
|
|
_SaveProtocolInfo(plugin);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2021-06-24 12:22:34 -05:00
|
|
|
|
PurpleApp::_SaveProtocolInfo(PurplePlugin* plugin)
|
2021-06-23 23:57:27 -05:00
|
|
|
|
{
|
|
|
|
|
ProtocolInfo* proto = new ProtocolInfo;
|
2021-07-05 12:42:20 -05:00
|
|
|
|
proto->id = purple_plugin_get_id(plugin);
|
|
|
|
|
proto->name = purple_plugin_get_name(plugin);
|
2021-06-24 12:22:34 -05:00
|
|
|
|
|
|
|
|
|
PurplePluginProtocolInfo* info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
|
2021-07-04 11:31:32 -05:00
|
|
|
|
proto->accountTemplate = _GetAccountTemplate(info);
|
|
|
|
|
proto->roomTemplate = _GetRoomTemplate(info);
|
2021-07-07 15:02:59 -05:00
|
|
|
|
if (info->list_icon != NULL)
|
|
|
|
|
proto->iconName = info->list_icon(NULL, NULL);
|
2021-06-23 23:57:27 -05:00
|
|
|
|
fProtocols.AddItem(proto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-24 12:22:34 -05:00
|
|
|
|
BMessage
|
2021-07-04 11:31:32 -05:00
|
|
|
|
PurpleApp::_GetAccountTemplate(PurplePluginProtocolInfo* info)
|
2021-06-24 12:22:34 -05:00
|
|
|
|
{
|
|
|
|
|
BMessage temp;
|
|
|
|
|
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― Account template"
|
|
|
|
|
|
2021-06-26 20:40:39 -05:00
|
|
|
|
// Add a "username" setting, if not explicitly specified
|
2021-06-24 12:22:34 -05:00
|
|
|
|
GList* prefIter = info->protocol_options;
|
2021-06-26 20:40:39 -05:00
|
|
|
|
for (int i = 0; prefIter != NULL; prefIter = prefIter->next) {
|
|
|
|
|
PurpleAccountOption* pref = (PurpleAccountOption*)prefIter->data;
|
|
|
|
|
|
|
|
|
|
if (pref->pref_name == BString("username"))
|
|
|
|
|
break;
|
|
|
|
|
else if (prefIter->next == NULL) {
|
|
|
|
|
BMessage setting;
|
|
|
|
|
setting.AddString("name", "username");
|
2021-07-18 21:51:38 -05:00
|
|
|
|
setting.AddString("description", B_TRANSLATE("Username:"));
|
|
|
|
|
setting.AddString("error",
|
|
|
|
|
B_TRANSLATE("A username needs to be specified!"));
|
2021-06-26 20:40:39 -05:00
|
|
|
|
setting.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
temp.AddMessage("setting", &setting);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 12:13:24 -05:00
|
|
|
|
// Add any UserSplits (that is, parts of the protocol's "username" format)
|
2021-06-26 20:40:39 -05:00
|
|
|
|
GList* splitIter = info->user_splits;
|
|
|
|
|
for (int i = 0; splitIter != NULL; splitIter = splitIter->next)
|
|
|
|
|
{
|
|
|
|
|
PurpleAccountUserSplit* split = (PurpleAccountUserSplit*)splitIter->data;
|
|
|
|
|
BMessage setting;
|
|
|
|
|
setting.AddString("name", "username_split");
|
2021-07-18 21:51:38 -05:00
|
|
|
|
setting.AddString("description", BString(_tr(split->text)).Append(":"));
|
2021-06-26 20:40:39 -05:00
|
|
|
|
setting.AddString("default", split->default_value);
|
|
|
|
|
setting.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
temp.AddMessage("setting", &setting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Password setting
|
|
|
|
|
BMessage passwd;
|
|
|
|
|
passwd.AddString("name", "password");
|
2021-07-18 21:51:38 -05:00
|
|
|
|
passwd.AddString("description", B_TRANSLATE("Password:"));
|
2021-06-26 20:40:39 -05:00
|
|
|
|
passwd.AddInt32("type", B_STRING_TYPE);
|
2021-07-02 09:19:58 -05:00
|
|
|
|
passwd.AddBool("is_secret", true);
|
2021-06-26 20:40:39 -05:00
|
|
|
|
temp.AddMessage("setting", &passwd);
|
|
|
|
|
|
|
|
|
|
// Whatever custom settings the protocol might like!
|
|
|
|
|
prefIter = info->protocol_options;
|
2021-06-24 12:22:34 -05:00
|
|
|
|
for (int i = 0; prefIter != NULL; prefIter = prefIter->next)
|
|
|
|
|
{
|
|
|
|
|
PurpleAccountOption* pref = (PurpleAccountOption*)prefIter->data;
|
|
|
|
|
PurplePrefType type = pref->type;
|
|
|
|
|
int32 bType;
|
|
|
|
|
|
|
|
|
|
BMessage setting;
|
|
|
|
|
setting.AddString("name", pref->pref_name);
|
2021-07-18 21:51:38 -05:00
|
|
|
|
BString description = BString(_tr(pref->text)).Append(":");
|
2021-06-24 12:22:34 -05:00
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case PURPLE_PREF_BOOLEAN:
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
description = _tr(pref->text);
|
2021-06-24 12:22:34 -05:00
|
|
|
|
bType = B_BOOL_TYPE;
|
|
|
|
|
setting.AddBool("default", pref->default_value.boolean);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case PURPLE_PREF_INT:
|
|
|
|
|
{
|
|
|
|
|
bType = B_INT32_TYPE;
|
|
|
|
|
setting.AddInt32("default", pref->default_value.integer);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-26 21:37:24 -05:00
|
|
|
|
case PURPLE_PREF_PATH_LIST:
|
|
|
|
|
case PURPLE_PREF_STRING_LIST:
|
|
|
|
|
{
|
|
|
|
|
bType = B_STRING_TYPE;
|
|
|
|
|
GList* list = pref->default_value.list;
|
|
|
|
|
for (int i = 0; list != NULL; list = list->next) {
|
|
|
|
|
PurpleKeyValuePair* pair = (PurpleKeyValuePair*)list->data;
|
|
|
|
|
setting.AddString("valid_value", pair->key);
|
|
|
|
|
if (pair->value ==
|
|
|
|
|
purple_account_option_get_default_list_value(pref))
|
|
|
|
|
temp.AddString(pref->pref_name, pair->key);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-24 12:22:34 -05:00
|
|
|
|
default:
|
|
|
|
|
bType = B_STRING_TYPE;
|
|
|
|
|
setting.AddString("default", pref->default_value.string);
|
|
|
|
|
}
|
2021-07-02 13:47:47 -05:00
|
|
|
|
|
2021-06-24 12:22:34 -05:00
|
|
|
|
if (pref->masked)
|
|
|
|
|
setting.AddBool("is_hidden", true);
|
2021-07-18 21:51:38 -05:00
|
|
|
|
|
|
|
|
|
BString error(B_TRANSLATE("%name% needs to be specified."));
|
|
|
|
|
error.ReplaceAll("%name%", pref->text);
|
|
|
|
|
setting.AddString("error", error);
|
|
|
|
|
|
2021-06-24 12:22:34 -05:00
|
|
|
|
setting.AddInt32("type", bType);
|
2021-07-02 13:47:47 -05:00
|
|
|
|
setting.AddString("description", description);
|
2021-06-24 12:22:34 -05:00
|
|
|
|
temp.AddMessage("setting", &setting);
|
|
|
|
|
}
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-04 11:31:32 -05:00
|
|
|
|
BMessage
|
|
|
|
|
PurpleApp::_GetRoomTemplate(PurplePluginProtocolInfo* info)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― Room template"
|
|
|
|
|
|
2021-07-04 11:31:32 -05:00
|
|
|
|
BMessage settings;
|
|
|
|
|
if (info->chat_info == NULL) {
|
|
|
|
|
settings.AddString("name", "chat_id");
|
2021-07-18 21:51:38 -05:00
|
|
|
|
settings.AddString("description", B_TRANSLATE("Room ID"));
|
2021-07-04 11:31:32 -05:00
|
|
|
|
settings.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GList* prefs = info->chat_info(NULL);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; prefs != NULL; prefs = prefs->next) {
|
|
|
|
|
BMessage setting;
|
|
|
|
|
proto_chat_entry* pref = (proto_chat_entry*)prefs->data;
|
|
|
|
|
|
|
|
|
|
setting.AddString("name", pref->identifier);
|
2021-07-18 21:51:38 -05:00
|
|
|
|
setting.AddString("description", _tr(pref->label));
|
2021-07-04 11:31:32 -05:00
|
|
|
|
|
2021-07-18 21:51:38 -05:00
|
|
|
|
if (pref->required) {
|
|
|
|
|
BString error(B_TRANSLATE("%name% is necessary."));
|
|
|
|
|
error.ReplaceAll("%name%", pref->identifier);
|
|
|
|
|
setting.AddString("error", error);
|
|
|
|
|
}
|
2021-07-04 11:31:32 -05:00
|
|
|
|
if (pref->secret)
|
|
|
|
|
setting.AddBool("is_secret", true);
|
|
|
|
|
if (pref->is_int)
|
|
|
|
|
setting.AddInt32("type", B_INT32_TYPE);
|
|
|
|
|
else
|
|
|
|
|
setting.AddInt32("type", B_STRING_TYPE);
|
|
|
|
|
|
|
|
|
|
settings.AddMessage("setting", &setting);
|
|
|
|
|
}
|
|
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-05 23:56:59 -05:00
|
|
|
|
BMessage
|
|
|
|
|
PurpleApp::_GetCommands(PurpleAccount* account)
|
|
|
|
|
{
|
|
|
|
|
PurpleConversation* conv = purple_conversation_new(PURPLE_CONV_TYPE_ANY,
|
|
|
|
|
account, NULL);
|
|
|
|
|
|
|
|
|
|
BMessage cmdMsgs(PURPLE_REGISTER_COMMANDS);
|
|
|
|
|
GList* cmds = purple_cmd_list(conv);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; cmds != NULL; cmds = cmds->next) {
|
|
|
|
|
const char* cmd_name = (const char*)cmds->data;
|
|
|
|
|
if (cmd_name == NULL) break;;
|
|
|
|
|
|
|
|
|
|
BMessage cmdMsg;
|
|
|
|
|
cmdMsg.AddString("class", "ChatCommand");
|
|
|
|
|
cmdMsg.AddString("_name", cmd_name);
|
|
|
|
|
cmdMsg.AddBool("_proto", true);
|
|
|
|
|
cmdMsg.AddInt32("_argtype", 0);
|
|
|
|
|
|
|
|
|
|
BString helpString;
|
|
|
|
|
GList* helps = purple_cmd_help(NULL, cmd_name);
|
|
|
|
|
for (int j = 0; helps != NULL; helps = helps->next)
|
|
|
|
|
helpString << (const char*)helps->data;
|
|
|
|
|
cmdMsg.AddString("_desc", helpString);
|
|
|
|
|
|
|
|
|
|
BMessage cmdActionMsg(IM_MESSAGE);
|
|
|
|
|
cmdActionMsg.AddInt32("im_what", PURPLE_CHAT_COMMAND);
|
|
|
|
|
cmdActionMsg.AddString("cmd_name", cmd_name);
|
|
|
|
|
cmdMsg.AddMessage("_msg", &cmdActionMsg);
|
|
|
|
|
|
|
|
|
|
cmdMsgs.AddMessage("command", &cmdMsg);
|
|
|
|
|
}
|
|
|
|
|
return cmdMsgs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-26 20:40:39 -05:00
|
|
|
|
void
|
2021-07-04 11:31:32 -05:00
|
|
|
|
PurpleApp::_ParseAccountTemplate(BMessage* settings)
|
2021-06-26 20:40:39 -05:00
|
|
|
|
{
|
|
|
|
|
PurplePlugin* plugin = _PluginFromMessage(settings);
|
|
|
|
|
PurplePluginProtocolInfo* info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
|
2021-06-27 16:46:38 -05:00
|
|
|
|
const char* protoId = settings->FindString("protocol");
|
2021-06-26 20:40:39 -05:00
|
|
|
|
|
|
|
|
|
if (plugin == NULL || info == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Fetch and cobble together the username & password
|
|
|
|
|
BString username, password;
|
|
|
|
|
settings->FindString("username", &username);
|
|
|
|
|
settings->FindString("password", &password);
|
|
|
|
|
|
|
|
|
|
GList* splitIter = info->user_splits;
|
|
|
|
|
for (int i = 0; splitIter != NULL; splitIter = splitIter->next)
|
|
|
|
|
{
|
|
|
|
|
PurpleAccountUserSplit* split = (PurpleAccountUserSplit*)splitIter->data;
|
|
|
|
|
username << split->field_sep;
|
|
|
|
|
|
|
|
|
|
BString opt;
|
|
|
|
|
if (settings->FindString("username_split", i, &opt) == B_OK)
|
|
|
|
|
username << opt;
|
|
|
|
|
else
|
|
|
|
|
username << split->default_value;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create/fetch the account itself
|
|
|
|
|
PurpleAccount* account = purple_accounts_find(username.String(), protoId);
|
|
|
|
|
if (account == NULL) {
|
|
|
|
|
account = purple_account_new(username.String(), protoId);
|
|
|
|
|
purple_accounts_add(account);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-27 16:46:38 -05:00
|
|
|
|
purple_account_set_password(account, password.String());
|
|
|
|
|
|
2021-06-26 20:40:39 -05:00
|
|
|
|
// Set all protocol settings
|
|
|
|
|
GList* prefIter = info->protocol_options;
|
|
|
|
|
for (int i = 0; prefIter != NULL; prefIter = prefIter->next)
|
|
|
|
|
{
|
|
|
|
|
PurpleAccountOption* pref = (PurpleAccountOption*)prefIter->data;
|
|
|
|
|
PurplePrefType type = pref->type;
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case PURPLE_PREF_BOOLEAN:
|
|
|
|
|
{
|
|
|
|
|
bool value;
|
|
|
|
|
if (settings->FindBool(pref->pref_name, &value) == B_OK)
|
|
|
|
|
purple_account_set_bool(account, pref->pref_name, value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case PURPLE_PREF_INT:
|
|
|
|
|
{
|
|
|
|
|
int32 value;
|
|
|
|
|
if (settings->FindInt32(pref->pref_name, &value) == B_OK)
|
|
|
|
|
purple_account_set_int(account, pref->pref_name, value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-06-26 21:37:24 -05:00
|
|
|
|
case PURPLE_PREF_PATH_LIST:
|
|
|
|
|
case PURPLE_PREF_STRING_LIST:
|
2021-06-26 20:40:39 -05:00
|
|
|
|
{
|
2021-06-26 21:37:24 -05:00
|
|
|
|
GList* list = pref->default_value.list;
|
|
|
|
|
BString value = settings->FindString(pref->pref_name);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; list != NULL; list = list->next) {
|
|
|
|
|
PurpleKeyValuePair* pair = (PurpleKeyValuePair*)list->data;
|
|
|
|
|
if (pair->key == value) {
|
|
|
|
|
purple_account_set_string(account, pref->pref_name,
|
|
|
|
|
(const char*)pair->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
2021-06-26 20:40:39 -05:00
|
|
|
|
BString value;
|
|
|
|
|
if (settings->FindString(pref->pref_name, &value) == B_OK)
|
|
|
|
|
purple_account_set_string(account, pref->pref_name,
|
|
|
|
|
value.String());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fAccounts.AddItem(settings->FindString("account_name"), username);
|
2021-06-27 16:46:38 -05:00
|
|
|
|
purple_account_set_enabled(account, PURPLE_UI_ID, true);
|
2021-06-26 20:40:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-05 12:42:20 -05:00
|
|
|
|
GHashTable*
|
|
|
|
|
PurpleApp::_ParseRoomTemplate(BMessage* msg)
|
|
|
|
|
{
|
|
|
|
|
PurplePlugin* plugin = _PluginFromMessage(msg);
|
|
|
|
|
PurplePluginProtocolInfo* info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
|
|
|
|
|
|
|
|
|
|
if (info->chat_info == NULL && info->chat_info_defaults != NULL)
|
|
|
|
|
return info->chat_info_defaults(_ConnectionFromMessage(msg),
|
|
|
|
|
msg->FindString("chat_id"));
|
|
|
|
|
else if (info->chat_info == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
GHashTable* table
|
|
|
|
|
= g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
|
|
|
|
|
|
|
|
|
|
GList* prefs = info->chat_info(NULL);
|
|
|
|
|
for (int i = 0; prefs != NULL; prefs = prefs->next) {
|
|
|
|
|
BString setting;
|
|
|
|
|
proto_chat_entry* pref = (proto_chat_entry*)prefs->data;
|
|
|
|
|
if (msg->FindString(pref->identifier, &setting) == B_OK)
|
|
|
|
|
g_hash_table_insert(table, (void*)pref->identifier, g_strdup(setting.String()));
|
|
|
|
|
}
|
|
|
|
|
return table;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-26 20:40:39 -05:00
|
|
|
|
PurplePlugin*
|
|
|
|
|
PurpleApp::_PluginFromMessage(BMessage* msg)
|
|
|
|
|
{
|
2021-06-27 16:46:38 -05:00
|
|
|
|
return purple_plugins_find_with_id(msg->FindString("protocol"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-05 12:42:20 -05:00
|
|
|
|
PurpleConnection*
|
|
|
|
|
PurpleApp::_ConnectionFromMessage(BMessage* msg)
|
|
|
|
|
{
|
|
|
|
|
return purple_account_get_connection(_AccountFromMessage(msg));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 16:46:38 -05:00
|
|
|
|
PurpleAccount*
|
|
|
|
|
PurpleApp::_AccountFromMessage(BMessage* msg)
|
|
|
|
|
{
|
|
|
|
|
BString protocol = msg->FindString("protocol");
|
|
|
|
|
BString username = fAccounts.ValueFor(msg->FindString("account_name"));
|
|
|
|
|
return purple_accounts_find(username.String(), protocol.String());
|
2021-06-26 20:40:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-28 12:51:50 -05:00
|
|
|
|
PurpleConversation*
|
|
|
|
|
PurpleApp::_ConversationFromMessage(BMessage* msg)
|
|
|
|
|
{
|
|
|
|
|
PurpleAccount* account = _AccountFromMessage(msg);
|
|
|
|
|
BString chat_id = msg->FindString("chat_id");
|
|
|
|
|
|
|
|
|
|
return purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
|
|
|
|
|
chat_id.String(), account);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-23 23:57:27 -05:00
|
|
|
|
status_t
|
|
|
|
|
init_libpurple()
|
|
|
|
|
{
|
2021-06-27 16:46:38 -05:00
|
|
|
|
init_ui_ops();
|
2021-06-23 23:57:27 -05:00
|
|
|
|
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
purple_util_set_user_dir(purple_cache());
|
|
|
|
|
|
|
|
|
|
BString cachePlugin = BString(purple_cache()).Append("/plugins/");
|
|
|
|
|
purple_plugins_add_search_path(cachePlugin.String());
|
2021-07-01 18:34:56 -05:00
|
|
|
|
purple_plugins_add_finddir(B_USER_LIB_DIRECTORY);
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
purple_plugins_add_finddir(B_USER_NONPACKAGED_LIB_DIRECTORY);
|
|
|
|
|
purple_plugins_add_finddir(B_SYSTEM_NONPACKAGED_LIB_DIRECTORY);
|
|
|
|
|
|
2021-07-17 14:18:06 -05:00
|
|
|
|
BPath ssl;
|
|
|
|
|
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &ssl) == B_OK) {
|
|
|
|
|
ssl.Append("ssl");
|
|
|
|
|
purple_certificate_add_ca_search_path(ssl.Path());
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-10 09:25:54 -05:00
|
|
|
|
purple_debug_set_enabled(DEBUG_ENABLED);
|
|
|
|
|
|
2021-06-27 16:46:38 -05:00
|
|
|
|
if (!purple_core_init(PURPLE_UI_ID))
|
2021-06-23 23:57:27 -05:00
|
|
|
|
return B_ERROR;
|
2021-06-27 16:46:38 -05:00
|
|
|
|
|
|
|
|
|
purple_set_blist(purple_blist_new());
|
|
|
|
|
purple_blist_load();
|
|
|
|
|
|
|
|
|
|
init_signals();
|
2021-06-23 23:57:27 -05:00
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-18 21:51:38 -05:00
|
|
|
|
void
|
|
|
|
|
init_gettext()
|
|
|
|
|
{
|
|
|
|
|
// Spoof the current language
|
|
|
|
|
BLocale locale;
|
|
|
|
|
BLanguage lang;
|
|
|
|
|
if (locale.GetLanguage(&lang) == B_OK)
|
|
|
|
|
setenv("LC_MESSAGES", lang.Code(), 1);
|
|
|
|
|
|
|
|
|
|
bindtextdomain("pidgin", "/boot/system/data/locale");
|
|
|
|
|
bind_textdomain_codeset("pidgin", "UTF-8");
|
|
|
|
|
textdomain("pidgin");
|
|
|
|
|
|
|
|
|
|
setlocale(LC_MESSAGES, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-06 00:56:16 -05:00
|
|
|
|
static PurpleEventLoopUiOps _ui_op_eventloops =
|
|
|
|
|
{
|
|
|
|
|
g_timeout_add,
|
|
|
|
|
g_source_remove,
|
|
|
|
|
ui_op_input_add,
|
|
|
|
|
g_source_remove,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2021-07-11 15:22:49 -05:00
|
|
|
|
static PurpleRequestUiOps _ui_op_request =
|
|
|
|
|
{
|
|
|
|
|
ui_op_request_input,
|
|
|
|
|
ui_op_request_choice,
|
|
|
|
|
ui_op_request_action,
|
|
|
|
|
ui_op_request_fields,
|
|
|
|
|
ui_op_request_file,
|
|
|
|
|
NULL,
|
|
|
|
|
ui_op_request_folder,
|
|
|
|
|
ui_op_request_action_with_icon,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2021-07-12 10:09:29 -05:00
|
|
|
|
static PurpleNotifyUiOps _ui_op_notify =
|
|
|
|
|
{
|
|
|
|
|
ui_op_notify_message,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 16:46:38 -05:00
|
|
|
|
void
|
|
|
|
|
init_ui_ops()
|
|
|
|
|
{
|
2021-07-06 00:56:16 -05:00
|
|
|
|
purple_eventloop_set_ui_ops(&_ui_op_eventloops);
|
2021-07-11 15:22:49 -05:00
|
|
|
|
purple_request_set_ui_ops(&_ui_op_request);
|
2021-07-12 10:09:29 -05:00
|
|
|
|
purple_notify_set_ui_ops(&_ui_op_notify);
|
2021-06-27 16:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_signals()
|
|
|
|
|
{
|
|
|
|
|
int handle;
|
2021-06-27 20:42:37 -05:00
|
|
|
|
|
|
|
|
|
purple_signal_connect(purple_connections_get_handle(), "connection-error",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_connection_error), NULL);
|
|
|
|
|
|
2021-06-28 12:13:24 -05:00
|
|
|
|
purple_signal_connect(purple_accounts_get_handle(), "account-signed-on",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_account_signed_on), NULL);
|
2021-07-18 13:52:24 -05:00
|
|
|
|
purple_signal_connect(purple_accounts_get_handle(), "account-signed-off",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_account_signed_off), NULL);
|
|
|
|
|
purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_account_disabled), NULL);
|
|
|
|
|
purple_signal_connect(purple_accounts_get_handle(), "account-error-changed",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_account_error_changed), NULL);
|
2021-06-28 12:13:24 -05:00
|
|
|
|
purple_signal_connect(purple_accounts_get_handle(), "account-status-changed",
|
2021-06-27 20:42:37 -05:00
|
|
|
|
&handle, PURPLE_CALLBACK(signal_account_status_changed), NULL);
|
2021-06-28 12:13:24 -05:00
|
|
|
|
|
2021-07-01 18:34:56 -05:00
|
|
|
|
purple_signal_connect(purple_blist_get_handle(), "blist-node-added",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_blist_node_added), NULL);
|
|
|
|
|
purple_signal_connect(purple_blist_get_handle(), "blist-node-removed",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_blist_node_removed), NULL);
|
2021-07-15 16:41:22 -05:00
|
|
|
|
purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_buddy_status_changed), NULL);
|
2021-07-01 18:34:56 -05:00
|
|
|
|
|
2021-06-28 12:13:24 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-joined",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_joined), NULL);
|
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-left",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_left), NULL);
|
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "received-chat-msg",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_received_chat_msg), NULL);
|
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "received-im-msg",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_received_chat_msg), NULL);
|
2021-06-29 20:02:45 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "sent-chat-msg",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_sent_chat_msg), NULL);
|
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_sent_im_msg), NULL);
|
2021-06-29 15:20:27 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-buddy-joined",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_buddy_joined), NULL);
|
2021-07-15 16:41:22 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-buddy-left",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_buddy_left), NULL);
|
2021-07-01 19:49:39 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-invited",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_invited), NULL);
|
2021-07-06 12:08:51 -05:00
|
|
|
|
purple_signal_connect(purple_conversations_get_handle(), "chat-buddy-flags",
|
|
|
|
|
&handle, PURPLE_CALLBACK(signal_chat_buddy_flags), NULL);
|
2021-06-27 16:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-06-28 12:13:24 -05:00
|
|
|
|
signal_connection_error(PurpleConnection* gc, PurpleConnectionError err,
|
|
|
|
|
const gchar* desc)
|
2021-06-27 16:46:38 -05:00
|
|
|
|
{
|
2021-06-28 12:13:24 -05:00
|
|
|
|
std::cerr << "Connection failed: " << (const char*)desc << std::endl;
|
2021-06-27 16:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-06-28 12:13:24 -05:00
|
|
|
|
signal_account_signed_on(PurpleAccount* account)
|
2021-06-27 16:46:38 -05:00
|
|
|
|
{
|
2021-06-28 12:13:24 -05:00
|
|
|
|
BMessage readyMsg(IM_MESSAGE);
|
|
|
|
|
readyMsg.AddInt32("im_what", IM_PROTOCOL_READY);
|
|
|
|
|
PurpleApp* app = (PurpleApp*)be_app;
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, readyMsg);
|
|
|
|
|
|
2021-07-07 20:44:11 -05:00
|
|
|
|
BString username = purple_account_get_username(account);
|
|
|
|
|
BString display = purple_account_get_name_for_display(account);
|
|
|
|
|
|
2021-06-28 12:13:24 -05:00
|
|
|
|
BMessage info(IM_MESSAGE);
|
2021-07-07 20:44:11 -05:00
|
|
|
|
send_own_info(account);
|
|
|
|
|
|
|
|
|
|
((PurpleApp*)be_app)->fUserNicks.AddItem(username, display);
|
2021-06-27 16:46:38 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-18 13:52:24 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_account_signed_off(PurpleAccount* account)
|
|
|
|
|
{
|
|
|
|
|
signal_account_disabled(account);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_account_disabled(PurpleAccount* account)
|
|
|
|
|
{
|
Redesign add-on disconnection
Currently, add-ons are disconnected when ChatProtocol::Shutdown() is
called, which the add-on can do by itself― but there is no standard way
for add-ons to notify the app about their Shutdown. Because of this,
they tend to not call Shutdown()― instead (as in the case of the Jabber
add-on), they display a BAlert (IM_ERROR) notifying the user of the
connection error, but the account is considered active by Cardie (and
its threads are still existant, including its ProtocolLooper).
Zombies are bad, so this is redesigned somewhat with this commit:
Protocols should no longer call ChatProtocol::Shutdown() themselves,
they must send an IM_MESSAGE of IM_PROTOCOL_DISABLE to the app.
This will delete its ProtocolLooper, which in turn will send a
notification to the user and delete the ChatProtocol, and so
calling ChatProtocol::Shutdown().
In the included protocols, an IM_ERROR is sent right before
IM_PROTOCOL_DISABLE is sent if due to a connection error. This is not
required, but it is courteous to inform your user about the "why." :)
2021-07-18 17:52:36 -05:00
|
|
|
|
BMessage disabled(PURPLE_SHUTDOWN_ADDON);
|
2021-07-18 13:52:24 -05:00
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, disabled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_account_error_changed(PurpleAccount* account,
|
|
|
|
|
const PurpleConnectionErrorInfo* old_error,
|
|
|
|
|
const PurpleConnectionErrorInfo* current_error)
|
|
|
|
|
{
|
|
|
|
|
if (current_error == NULL) return;
|
|
|
|
|
|
|
|
|
|
BMessage error(IM_ERROR);
|
|
|
|
|
error.AddString("error", purple_connection_error_name(current_error));
|
|
|
|
|
error.AddString("detail", current_error->description);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 20:42:37 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_account_status_changed(PurpleAccount* account, PurpleStatus* old,
|
|
|
|
|
PurpleStatus* cur)
|
|
|
|
|
{
|
|
|
|
|
BMessage own(IM_MESSAGE);
|
|
|
|
|
own.AddInt32("im_what", IM_OWN_STATUS_SET);
|
|
|
|
|
own.AddInt32("status", purple_status_to_cardie(cur));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, own);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-01 18:34:56 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_blist_node_added(PurpleBlistNode* node)
|
|
|
|
|
{
|
|
|
|
|
PurpleBuddy* buddy;
|
|
|
|
|
if (PURPLE_BLIST_NODE_IS_BUDDY(node))
|
|
|
|
|
buddy = PURPLE_BUDDY(node);
|
|
|
|
|
else if (PURPLE_BLIST_NODE_IS_CONTACT(node))
|
|
|
|
|
buddy = purple_contact_get_priority_buddy(PURPLE_CONTACT(node));
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
BMessage add(IM_MESSAGE);
|
|
|
|
|
add.AddInt32("im_what", IM_CONTACT_LIST);
|
|
|
|
|
add.AddString("user_id", purple_buddy_get_name(buddy));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_buddy_get_account(buddy), add);
|
|
|
|
|
|
|
|
|
|
BString alias = purple_buddy_get_local_alias(buddy);
|
|
|
|
|
if (alias.IsEmpty() == true)
|
|
|
|
|
alias.SetTo(purple_buddy_get_server_alias(buddy));
|
|
|
|
|
|
|
|
|
|
BMessage name(IM_MESSAGE);
|
|
|
|
|
name.AddInt32("im_what", IM_CONTACT_INFO);
|
|
|
|
|
name.AddString("user_id", purple_buddy_get_name(buddy));
|
|
|
|
|
if (alias.IsEmpty() == false)
|
|
|
|
|
name.AddString("user_name", alias);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_buddy_get_account(buddy), name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_blist_node_removed(PurpleBlistNode* node)
|
|
|
|
|
{
|
|
|
|
|
PurpleBuddy* buddy;
|
|
|
|
|
if (PURPLE_BLIST_NODE_IS_BUDDY(node))
|
|
|
|
|
buddy = PURPLE_BUDDY(node);
|
|
|
|
|
else if (PURPLE_BLIST_NODE_IS_CONTACT(node))
|
|
|
|
|
buddy = purple_contact_get_priority_buddy(PURPLE_CONTACT(node));
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
BMessage rem(IM_MESSAGE);
|
|
|
|
|
rem.AddInt32("im_what", IM_CONTACT_LIST_CONTACT_REMOVED);
|
|
|
|
|
rem.AddString("user_id", purple_buddy_get_name(buddy));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_buddy_get_account(buddy), rem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-15 16:41:22 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_buddy_status_changed(PurpleBuddy* buddy, PurpleStatus* old_status,
|
|
|
|
|
PurpleStatus* status)
|
|
|
|
|
{
|
|
|
|
|
BMessage note(IM_MESSAGE);
|
|
|
|
|
note.AddInt32("im_what", IM_STATUS_SET);
|
|
|
|
|
note.AddInt32("status", purple_status_to_cardie(status));
|
|
|
|
|
note.AddString("user_id", purple_buddy_get_name(buddy));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_buddy_get_account(buddy), note);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-28 12:13:24 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_chat_joined(PurpleConversation* conv)
|
|
|
|
|
{
|
|
|
|
|
BMessage join(IM_MESSAGE);
|
|
|
|
|
join.AddInt32("im_what", IM_ROOM_JOINED);
|
|
|
|
|
join.AddString("chat_id", purple_conversation_get_name(conv));
|
2021-06-29 15:20:27 -05:00
|
|
|
|
|
|
|
|
|
PurpleAccount* account = purple_conversation_get_account(conv);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, join);
|
2021-06-28 12:13:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_chat_left(PurpleConversation* conv)
|
|
|
|
|
{
|
|
|
|
|
BMessage left(IM_MESSAGE);
|
|
|
|
|
left.AddInt32("im_what", IM_ROOM_LEFT);
|
|
|
|
|
left.AddString("chat_id", purple_conversation_get_name(conv));
|
2021-06-29 15:20:27 -05:00
|
|
|
|
|
|
|
|
|
PurpleAccount* account = purple_conversation_get_account(conv);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, left);
|
2021-06-28 12:13:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_received_chat_msg(PurpleAccount* account, char* sender, char* message,
|
|
|
|
|
PurpleConversation* conv, PurpleMessageFlags flags)
|
|
|
|
|
{
|
2021-07-09 11:53:16 -05:00
|
|
|
|
if (is_own_user(account, sender) == true)
|
2021-07-06 00:56:16 -05:00
|
|
|
|
return;
|
|
|
|
|
|
2021-06-29 20:02:45 -05:00
|
|
|
|
BString chat_id = BString(purple_conversation_get_name(conv));
|
|
|
|
|
if (chat_id.IsEmpty() == true)
|
|
|
|
|
chat_id = sender;
|
|
|
|
|
|
2021-07-06 14:27:14 -05:00
|
|
|
|
PurpleConvChat* chat = purple_conversation_get_chat_data(conv);
|
|
|
|
|
|
|
|
|
|
BMessage msg(IM_MESSAGE);
|
|
|
|
|
msg.AddInt32("im_what", IM_MESSAGE_RECEIVED);
|
|
|
|
|
msg.AddString("chat_id", chat_id);
|
2021-07-17 14:18:06 -05:00
|
|
|
|
msg.AddString("user_id", sender);
|
2021-07-06 14:27:14 -05:00
|
|
|
|
msg.AddString("body", purple_unescape_text(message));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, msg);
|
2021-06-28 12:13:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-28 12:51:50 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_sent_chat_msg(PurpleAccount* account, const char* message, int conv_id)
|
|
|
|
|
{
|
|
|
|
|
PurpleConnection* gc = purple_account_get_connection(account);
|
|
|
|
|
PurpleConversation* conv = purple_find_chat(gc, conv_id);
|
|
|
|
|
|
|
|
|
|
BMessage sent(IM_MESSAGE);
|
|
|
|
|
sent.AddInt32("im_what", IM_MESSAGE_SENT);
|
|
|
|
|
sent.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
sent.AddString("user_id", purple_account_get_username(account));
|
2021-07-06 02:09:18 -05:00
|
|
|
|
sent.AddString("body", purple_unescape_text(message));
|
2021-06-28 12:51:50 -05:00
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, sent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
signal_sent_im_msg(PurpleAccount* account, const char* receiver,
|
|
|
|
|
const char* message)
|
|
|
|
|
{
|
|
|
|
|
BMessage sent(IM_MESSAGE);
|
|
|
|
|
sent.AddInt32("im_what", IM_MESSAGE_SENT);
|
|
|
|
|
sent.AddString("chat_id", receiver);
|
|
|
|
|
sent.AddString("user_id", purple_account_get_username(account));
|
2021-07-06 02:09:18 -05:00
|
|
|
|
sent.AddString("body", purple_unescape_text(message));
|
2021-06-28 12:51:50 -05:00
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, sent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-29 15:20:27 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_chat_buddy_joined(PurpleConversation* conv, const char* name,
|
|
|
|
|
PurpleConvChatBuddyFlags flags, gboolean new_arrival)
|
|
|
|
|
{
|
|
|
|
|
BMessage joined(IM_MESSAGE);
|
|
|
|
|
if (new_arrival)
|
|
|
|
|
joined.AddInt32("im_what", IM_ROOM_PARTICIPANT_JOINED);
|
2021-07-07 20:44:11 -05:00
|
|
|
|
else {
|
2021-06-29 15:20:27 -05:00
|
|
|
|
joined.AddInt32("im_what", IM_ROOM_PARTICIPANTS);
|
2021-07-07 20:44:11 -05:00
|
|
|
|
if (is_own_user(purple_conversation_get_account(conv), name) == true)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-06-29 15:20:27 -05:00
|
|
|
|
joined.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
joined.AddString("user_id", name);
|
2021-07-06 00:56:16 -05:00
|
|
|
|
|
2021-06-29 15:20:27 -05:00
|
|
|
|
PurpleAccount* account = purple_conversation_get_account(conv);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, joined);
|
2021-07-06 12:08:51 -05:00
|
|
|
|
|
|
|
|
|
send_user_role(conv, name, flags);
|
2021-06-29 15:20:27 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-15 16:41:22 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_chat_buddy_left(PurpleConversation* conv, const char* name,
|
|
|
|
|
const char* reason)
|
|
|
|
|
{
|
|
|
|
|
BMessage left(IM_MESSAGE);
|
|
|
|
|
left.AddInt32("im_what", IM_ROOM_PARTICIPANT_LEFT);
|
|
|
|
|
left.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
left.AddString("user_id", name);
|
|
|
|
|
left.AddString("body", reason);
|
|
|
|
|
PurpleAccount* account = purple_conversation_get_account(conv);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, left);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-01 19:49:39 -05:00
|
|
|
|
// inviter == user_id, not user_name
|
|
|
|
|
static void
|
|
|
|
|
signal_chat_invited(PurpleAccount* account, const char* inviter,
|
|
|
|
|
const char* chat, const char* message, const GHashTable* components)
|
|
|
|
|
{
|
|
|
|
|
PurpleApp* app = (PurpleApp*)be_app;
|
|
|
|
|
BString key(purple_account_get_username(account));
|
|
|
|
|
key = key.Append("-invite-").Append(chat);
|
|
|
|
|
|
|
|
|
|
GHashTable* data = (GHashTable*)components;
|
|
|
|
|
app->fInviteList.AddItem(key, data);
|
|
|
|
|
|
|
|
|
|
BMessage invited(IM_MESSAGE);
|
|
|
|
|
invited.AddInt32("im_what", IM_ROOM_INVITE_RECEIVED);
|
|
|
|
|
invited.AddString("chat_id", chat);
|
|
|
|
|
invited.AddString("user_id", inviter);
|
2021-07-06 02:09:18 -05:00
|
|
|
|
invited.AddString("body", purple_unescape_text(message));
|
2021-07-01 19:49:39 -05:00
|
|
|
|
app->SendMessage(account, invited);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-29 15:20:27 -05:00
|
|
|
|
|
2021-07-06 12:08:51 -05:00
|
|
|
|
static void
|
|
|
|
|
signal_chat_buddy_flags(PurpleConversation* conv, const char* name,
|
|
|
|
|
PurpleConvChatBuddyFlags oldflags, PurpleConvChatBuddyFlags newflags)
|
|
|
|
|
{
|
|
|
|
|
send_user_role(conv, name, newflags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-06 00:56:16 -05:00
|
|
|
|
static guint
|
|
|
|
|
ui_op_input_add(gint fd, PurpleInputCondition condition,
|
|
|
|
|
PurpleInputFunction function, gpointer data)
|
|
|
|
|
{
|
|
|
|
|
PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
|
|
|
|
|
GIOChannel *channel;
|
|
|
|
|
GIOCondition cond = (GIOCondition)0;
|
|
|
|
|
|
|
|
|
|
closure->function = function;
|
|
|
|
|
closure->data = data;
|
|
|
|
|
|
|
|
|
|
channel = g_io_channel_unix_new(fd);
|
|
|
|
|
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
|
|
|
|
|
_purple_glib_io_invoke, closure, g_free);
|
|
|
|
|
|
|
|
|
|
g_io_channel_unref(channel);
|
|
|
|
|
return closure->result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-11 15:22:49 -05:00
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_input(const char* title, const char* primary,
|
|
|
|
|
const char* secondary, const char* default_value, gboolean multiline,
|
|
|
|
|
gboolean masked, gchar* hint, const char* ok_text, GCallback ok_cb,
|
|
|
|
|
const char* cancel_text, GCallback cancel_cb, PurpleAccount* account,
|
|
|
|
|
const char* who, PurpleConversation* conv, void* user_data)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request input: " << title << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_choice(const char* title, const char* primary,
|
|
|
|
|
const char* secondary, int default_value, const char* ok_text,
|
|
|
|
|
GCallback ok_cb, const char* cancel_text, GCallback cancel_cb,
|
|
|
|
|
PurpleAccount* account, const char* who, PurpleConversation* conv,
|
|
|
|
|
void* user_data, va_list choices)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request choice: " << title << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_action(const char* title, const char* primary,
|
|
|
|
|
const char* secondary, int default_action, PurpleAccount* account,
|
|
|
|
|
const char* who, PurpleConversation* conv, void* user_data,
|
|
|
|
|
size_t action_count, va_list actions)
|
|
|
|
|
{
|
|
|
|
|
PurpleDialog* win =
|
|
|
|
|
new PurpleDialog(title, primary, secondary, account, actions,
|
|
|
|
|
action_count, user_data);
|
|
|
|
|
win->Show();
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_fields(const char* title, const char* primary,
|
|
|
|
|
const char* secondary, PurpleRequestFields* fields, const char* ok_text,
|
|
|
|
|
GCallback ok_cb, const char* cancel_text, GCallback cancel_cb,
|
|
|
|
|
PurpleAccount* account, const char* who, PurpleConversation* conv,
|
|
|
|
|
void* user_data)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request fields from " << purple_account_get_username(account)
|
|
|
|
|
<< ": " << primary << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_file(const char* title, const char* filename, gboolean savedialog,
|
|
|
|
|
GCallback ok_cb, GCallback cancel_cb, PurpleAccount* account,
|
|
|
|
|
const char* who, PurpleConversation* conv, void* user_data)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request file: " << title << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_folder(const char* title, const char* dirname, GCallback ok_cb,
|
|
|
|
|
GCallback cancel_cb, PurpleAccount* account, const char* who,
|
|
|
|
|
PurpleConversation* conv, void* user_data)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request folder: " << title << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void*
|
|
|
|
|
ui_op_request_action_with_icon(const char* title, const char* primary,
|
|
|
|
|
const char* secondary, int default_action, PurpleAccount* account,
|
|
|
|
|
const char* who, PurpleConversation* conv, gconstpointer icon_data,
|
|
|
|
|
gsize icon_size, void* user_data, size_t action_count, va_list actions)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "request action with icon: " << title << std::endl;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-12 10:09:29 -05:00
|
|
|
|
static void*
|
|
|
|
|
ui_op_notify_message(PurpleNotifyMsgType type, const char* title,
|
|
|
|
|
const char* primary, const char* secondary)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
BString text = _tr(primary);
|
|
|
|
|
text << "\n" << _tr(secondary);
|
2021-07-12 10:09:29 -05:00
|
|
|
|
|
|
|
|
|
BAlert* alert = new BAlert(title, text.String(), "OK");
|
|
|
|
|
|
|
|
|
|
if (type == PURPLE_NOTIFY_MSG_WARNING)
|
|
|
|
|
alert->SetType(B_WARNING_ALERT);
|
|
|
|
|
else if (type == PURPLE_NOTIFY_MSG_ERROR)
|
|
|
|
|
alert->SetType(B_STOP_ALERT);
|
|
|
|
|
|
|
|
|
|
alert->Go(NULL);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-07 20:44:11 -05:00
|
|
|
|
bool
|
|
|
|
|
is_own_user(PurpleAccount* account, const char* name)
|
|
|
|
|
{
|
|
|
|
|
PurpleApp* app = ((PurpleApp*)be_app);
|
|
|
|
|
BString username = purple_account_get_username(account);
|
|
|
|
|
BString display = purple_account_get_name_for_display(account);
|
|
|
|
|
|
|
|
|
|
if (app->fUserNicks.ValueFor(username) != display) {
|
|
|
|
|
app->fUserNicks.RemoveItemFor(username);
|
|
|
|
|
app->fUserNicks.AddItem(username, display);
|
|
|
|
|
send_own_info(account);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (name == username || name == display)
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
send_own_info(PurpleAccount* account)
|
|
|
|
|
{
|
|
|
|
|
BMessage info(IM_MESSAGE);
|
|
|
|
|
info.AddInt32("im_what", IM_OWN_CONTACT_INFO);
|
|
|
|
|
info.AddString("user_id", purple_account_get_username(account));
|
|
|
|
|
info.AddString("user_name", purple_account_get_name_for_display(account));
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(account, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-06 12:08:51 -05:00
|
|
|
|
void
|
|
|
|
|
send_user_role(PurpleConversation* conv, const char* name,
|
|
|
|
|
PurpleConvChatBuddyFlags flags)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― User roles"
|
|
|
|
|
|
2021-07-06 12:08:51 -05:00
|
|
|
|
if (flags == 0) return;
|
|
|
|
|
|
|
|
|
|
BString role_title;
|
|
|
|
|
int32 role_perms = 0 | PERM_READ | PERM_WRITE;
|
|
|
|
|
int32 role_priority = 0;
|
|
|
|
|
|
|
|
|
|
if (flags & PURPLE_CBFLAGS_FOUNDER) {
|
2021-07-18 21:51:38 -05:00
|
|
|
|
role_title = B_TRANSLATE("Founder");
|
2021-07-06 12:08:51 -05:00
|
|
|
|
role_priority = 3;
|
|
|
|
|
}
|
|
|
|
|
if (flags & PURPLE_CBFLAGS_OP) {
|
|
|
|
|
if (role_title.IsEmpty() == true)
|
2021-07-18 21:51:38 -05:00
|
|
|
|
role_title = B_TRANSLATE("Operator");
|
2021-07-06 14:13:10 -05:00
|
|
|
|
role_perms |= PERM_ROOM_SUBJECT | PERM_ROOM_NAME;
|
2021-07-06 12:08:51 -05:00
|
|
|
|
role_priority = 2;
|
|
|
|
|
}
|
|
|
|
|
if (flags & PURPLE_CBFLAGS_HALFOP) {
|
|
|
|
|
if (role_title.IsEmpty() == true)
|
2021-07-18 21:51:38 -05:00
|
|
|
|
role_title = B_TRANSLATE("Moderator");
|
2021-07-06 14:13:10 -05:00
|
|
|
|
role_perms |= PERM_ROOM_SUBJECT | PERM_ROOM_NAME;
|
2021-07-06 12:08:51 -05:00
|
|
|
|
role_priority = 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (role_title.IsEmpty() == true) return;
|
|
|
|
|
|
|
|
|
|
BMessage role(IM_MESSAGE);
|
|
|
|
|
role.AddInt32("im_what", IM_ROOM_ROLECHANGED);
|
|
|
|
|
role.AddString("user_id", name);
|
|
|
|
|
role.AddString("chat_id", purple_conversation_get_name(conv));
|
|
|
|
|
role.AddString("role_title", role_title);
|
|
|
|
|
role.AddInt32("role_perms", role_perms);
|
|
|
|
|
role.AddInt32("role_priority", role_priority);
|
|
|
|
|
((PurpleApp*)be_app)->SendMessage(purple_conversation_get_account(conv),
|
|
|
|
|
role);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-27 20:42:37 -05:00
|
|
|
|
PurpleStatusPrimitive
|
|
|
|
|
cardie_status_to_purple(UserStatus status)
|
|
|
|
|
{
|
|
|
|
|
PurpleStatusPrimitive type = PURPLE_STATUS_UNSET;
|
|
|
|
|
switch (status)
|
|
|
|
|
{
|
|
|
|
|
case STATUS_ONLINE:
|
|
|
|
|
type = PURPLE_STATUS_AVAILABLE;
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_AWAY:
|
|
|
|
|
type = PURPLE_STATUS_AWAY;
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_DO_NOT_DISTURB:
|
|
|
|
|
type = PURPLE_STATUS_UNAVAILABLE;
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_CUSTOM_STATUS:
|
|
|
|
|
type = PURPLE_STATUS_AVAILABLE;
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_INVISIBLE:
|
|
|
|
|
type = PURPLE_STATUS_INVISIBLE;
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_OFFLINE:
|
|
|
|
|
type = PURPLE_STATUS_OFFLINE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UserStatus
|
|
|
|
|
purple_status_to_cardie(PurpleStatus* status)
|
|
|
|
|
{
|
|
|
|
|
PurpleStatusPrimitive prim =
|
|
|
|
|
purple_status_type_get_primitive(purple_status_get_type(status));
|
|
|
|
|
|
|
|
|
|
switch (prim)
|
|
|
|
|
{
|
|
|
|
|
case PURPLE_STATUS_AWAY:
|
|
|
|
|
return STATUS_AWAY;
|
|
|
|
|
case PURPLE_STATUS_UNAVAILABLE:
|
|
|
|
|
return STATUS_DO_NOT_DISTURB;
|
|
|
|
|
break;
|
|
|
|
|
case PURPLE_STATUS_INVISIBLE:
|
|
|
|
|
return STATUS_INVISIBLE;
|
|
|
|
|
break;
|
|
|
|
|
case PURPLE_STATUS_OFFLINE:
|
|
|
|
|
return STATUS_OFFLINE;
|
|
|
|
|
}
|
|
|
|
|
return STATUS_ONLINE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-18 13:52:24 -05:00
|
|
|
|
const char*
|
|
|
|
|
purple_connection_error_name(const PurpleConnectionErrorInfo* error)
|
|
|
|
|
{
|
2021-07-18 21:51:38 -05:00
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
|
|
|
#define B_TRANSLATION_CONTEXT "PurpleApp ― Connection errors"
|
|
|
|
|
|
2021-07-18 13:52:24 -05:00
|
|
|
|
switch (error->type)
|
|
|
|
|
{
|
|
|
|
|
case PURPLE_CONNECTION_ERROR_NETWORK_ERROR:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Network error");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_INVALID_USERNAME:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Invalid username");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Authentication failed");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Authentication impossible");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("SSL unsupported");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Encryption error");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_NAME_IN_USE:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Username in use");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_INVALID_SETTINGS:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Settings invalid");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_NOT_PROVIDED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("No SSL certificate provided");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_UNTRUSTED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Untrusted SSL certificate");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_EXPIRED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Expired SSL certificate");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_NOT_ACTIVATED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Unactivated SSL certificate");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Certificate and hostname conflict");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Certifcate and fingerprint conflict");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_SELF_SIGNED:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Self-signed certificate");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
case PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR:
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Certificate error");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
}
|
2021-07-18 21:51:38 -05:00
|
|
|
|
return B_TRANSLATE("Connection error");
|
2021-07-18 13:52:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
const char*
|
|
|
|
|
purple_cache()
|
|
|
|
|
{
|
|
|
|
|
BPath path;
|
|
|
|
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
|
|
|
|
|
return NULL;
|
|
|
|
|
path.Append(APP_NAME "/Cache/Add-Ons/" PURPLE_ADDON);
|
|
|
|
|
if (create_directory(path.Path(), 0755) != B_OK)
|
|
|
|
|
return NULL;
|
|
|
|
|
return path.Path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
purple_plugins_add_finddir(directory_which finddir)
|
|
|
|
|
{
|
|
|
|
|
BPath path;
|
|
|
|
|
if (find_directory(finddir, &path) == B_OK) {
|
2021-07-01 18:34:56 -05:00
|
|
|
|
path.Append("purple-2");
|
Reorganize settings directory, custom purple paths
The settings file-hierarchy has been changed a bit:
* Cardie/
* preferences
* Accounts/
* Cache/
* Accounts/
* Add-Ons/
`Cardie/Protocols` is now `Cardie/Accounts`, and the cache directory
has been split into two. `Cache/Accounts/` is for account-specific
cached data (e.g., cached roster icons, data, etc.), and
`Cache/Protocols` is for protocol-wide settings/data.
For purple, this will be used as the user's libpurple directory,
which has been moved from the default of `~/.purple` (yikes!)
Some plugin search-paths have been given to purple, too― lib
directories + "/purple2/", and Cardie/Cache/Add-Ons/purple/plugins/.
2021-06-30 20:29:30 -05:00
|
|
|
|
purple_plugins_add_search_path(path.Path());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-06 00:56:16 -05:00
|
|
|
|
static gboolean
|
|
|
|
|
_purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
|
2021-06-23 23:57:27 -05:00
|
|
|
|
{
|
|
|
|
|
PurpleGLibIOClosure *closure = (PurpleGLibIOClosure*)data;
|
|
|
|
|
PurpleInputCondition purple_cond = (PurpleInputCondition)0;
|
|
|
|
|
|
|
|
|
|
closure->function(closure->data, g_io_channel_unix_get_fd(source),
|
|
|
|
|
purple_cond);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2021-07-18 21:51:38 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char*
|
|
|
|
|
_tr(const char* string)
|
|
|
|
|
{
|
|
|
|
|
return BString(dgettext("pidgin", string)).ReplaceFirst("_", "").String();
|
|
|
|
|
}
|