Libpurple + Libtransport: Support aliases in rooms, fix joining rooms on protocols where you cannot join with custom nickname, show topic in the service discovery for rooms.

This commit is contained in:
Jan Kaluza 2016-02-08 09:26:34 +01:00
parent dc6c6f8337
commit 9de5e656da
8 changed files with 89 additions and 35 deletions

View file

@ -704,14 +704,19 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, (room + "/" + nickname).c_str());
} else {
comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, room.c_str());
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE);
const char *disp;
if ((disp = purple_connection_get_display_name(account->gc))) {
handleRoomNicknameChanged(np->m_accounts[account], room, disp);
}
else {
handleRoomNicknameChanged(np->m_accounts[account], room, purple_account_get_username(account));
}
}
}
if (CONFIG_STRING(config, "service.protocol") != "prpl-jabber") {
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE);
const char *disp;
if ((disp = purple_connection_get_display_name(account->gc))) {
handleRoomNicknameChanged(np->m_accounts[account], room, disp);
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", disp);
}
else {
handleRoomNicknameChanged(np->m_accounts[account], room, purple_account_get_username(account));
np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", purple_account_get_username(account));
}
}
@ -1182,6 +1187,7 @@ static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gbool
while (l != NULL) {
PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data;
std::string name(cb->name);
std::string alias = cb->alias ? cb->alias : cb->name;
int flags = GPOINTER_TO_INT(cb->flags);
if (flags & PURPLE_CBFLAGS_OP || flags & PURPLE_CBFLAGS_HALFOP) {
// item->addAttribute("affiliation", "admin");
@ -1199,7 +1205,7 @@ static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gbool
// item->addAttribute("role", "participant");
}
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name_wrapped(conv), (int) flags, pbnetwork::STATUS_ONLINE);
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name_wrapped(conv), (int) flags, pbnetwork::STATUS_ONLINE, "", "", alias);
l = l->next;
}
@ -1597,14 +1603,47 @@ static PurpleXferUiOps xferUiOps =
static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress)
{
if (!in_progress)
{
if (!in_progress) {
GList *fields = purple_roomlist_get_fields(list);
GList *field;
int topicId = -1;
int id = 0;
for (field = fields; field != NULL; field = field->next, id++) {
PurpleRoomlistField *f = (PurpleRoomlistField *) field->data;
if (!f || !f->name) {
continue;
}
std::string fstring = f->name;
if (fstring == "topic") {
topicId = id;
}
else {
LOG4CXX_INFO(logger, "Uknown RoomList field " << fstring);
}
}
LOG4CXX_INFO(logger, "RoomList topic ID: " << topicId);
GList *rooms;
std::list<std::string> m_rooms;
for (rooms = list->rooms; rooms != NULL; rooms = rooms->next)
{
std::list<std::string> m_topics;
for (rooms = list->rooms; rooms != NULL; rooms = rooms->next) {
PurpleRoomlistRoom *room = (PurpleRoomlistRoom *)rooms->data;
m_rooms.push_back(room->name);
if (topicId == -1) {
m_topics.push_back(room->name);
}
else {
char *topic = (char *) g_list_nth_data(purple_roomlist_room_get_fields(room), topicId);
if (topic) {
m_topics.push_back(topic);
}
else {
LOG4CXX_WARN(logger, "RoomList topic is NULL");
m_topics.push_back(room->name);
}
}
}
std::string user = "";
@ -1613,7 +1652,7 @@ static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress)
}
LOG4CXX_INFO(logger, "RoomList is fetched for user " << user);
np->handleRoomList(user, m_rooms, m_rooms);
np->handleRoomList(user, m_rooms, m_topics);
}
else {
LOG4CXX_INFO(logger, "RoomList is still in progress");
@ -1928,6 +1967,9 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi
if (CONFIG_STRING(config, "service.protocol") == "prpl-telegram") {
cfg.setNeedPassword(false);
}
if (CONFIG_STRING(config, "service.protocol") != "prpl-irc") {
cfg.setNeedRegistration(false);
}
np->sendConfig(cfg);
}

View file

@ -44,12 +44,6 @@ class Conversation {
PARTICIPANT_FLAG_ROOM_NOT_FOUD = 64
} ParticipantFlag;
typedef struct _Participant {
ParticipantFlag flag;
int status;
std::string statusMessage;
} Participant;
/// Creates new conversation.
/// \param conversationManager ConversationManager associated with this Conversation.
@ -81,7 +75,7 @@ class Conversation {
/// \param status Current status of this participant.
/// \param statusMessage Current status message of this participant.
/// \param newname If participant was renamed, this variable contains his new name.
void handleParticipantChanged(const std::string &nickname, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = "", const std::string &iconhash = "");
void handleParticipantChanged(const std::string &nickname, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = "", const std::string &iconhash = "", const std::string &alias = "");
/// Sets XMPP user nickname in MUC rooms.
@ -176,7 +170,12 @@ class Conversation {
// every time, so we can get history messages for IRC for example.
boost::shared_ptr<Swift::Message> m_subject;
std::list<boost::shared_ptr<Swift::Message> > m_cachedMessages;
std::map<std::string, Swift::Presence::ref> m_participants;
typedef struct {
Swift::Presence::ref presence;
std::string alias;
} Participant;
std::map<std::string, Participant> m_participants;
};
}

View file

@ -103,7 +103,8 @@ class NetworkPlugin {
/// \param statusMessage Current status message of participant.
/// \param newname New name of participant if he changed the nickname. Otherwise empty.
void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags,
pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = "");
pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = "",
const std::string &alias = "");
/// Call this function when user disconnected the legacy network because of some legacy network error.
/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")

View file

@ -112,6 +112,7 @@ message Participant {
optional string statusMessage = 6;
optional string newname = 7;
optional string iconHash = 8;
optional string alias = 9;
}
message VCard {

View file

@ -207,6 +207,11 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
n = " ";
}
std::map<std::string, Participant>::iterator it = m_participants.find(n);
if (it != m_participants.end() && !it->second.alias.empty()) {
n = it->second.alias;
}
message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
LOG4CXX_INFO(logger, "MSG FROM " << message->getFrom().toString());
}
@ -216,16 +221,16 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
std::string Conversation::getParticipants() {
std::string ret;
for (std::map<std::string, Swift::Presence::ref>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
ret += (*it).second->getFrom().getResource() + ", ";
for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
ret += (*it).second.presence->getFrom().getResource() + ", ";
}
return ret;
}
void Conversation::sendParticipants(const Swift::JID &to) {
for (std::map<std::string, Swift::Presence::ref>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
(*it).second->setTo(to);
m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second);
for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
(*it).second.presence->setTo(to);
m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second.presence);
}
}
@ -352,17 +357,18 @@ void Conversation::setNickname(const std::string &nickname) {
void Conversation::handleRawPresence(Swift::Presence::ref presence) {
// TODO: Detect nickname change.
m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
m_participants[presence->getFrom().getResource()] = presence;
m_participants[presence->getFrom().getResource()].presence = presence;
}
void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash) {
Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname, iconhash);
void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash, const std::string &alias) {
Swift::Presence::ref presence = generatePresence(alias.empty() ? nick : alias, flag, status, statusMessage, newname, iconhash);
if (presence->getType() == Swift::Presence::Unavailable) {
m_participants.erase(nick);
}
else {
m_participants[nick] = presence;
m_participants[nick].presence = presence;
m_participants[nick].alias = alias;
}

View file

@ -636,7 +636,7 @@ void NetworkPluginServer::handleParticipantChangedPayload(const std::string &dat
return;
}
conv->handleParticipantChanged(payload.nickname(), (Conversation::ParticipantFlag) payload.flag(), payload.status(), payload.statusmessage(), payload.newname(), payload.iconhash());
conv->handleParticipantChanged(payload.nickname(), (Conversation::ParticipantFlag) payload.flag(), payload.status(), payload.statusmessage(), payload.newname(), payload.iconhash(), payload.alias());
}
void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) {
@ -646,11 +646,14 @@ void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) {
}
User *user = m_userManager->getUser(payload.username());
if (!user)
if (!user) {
LOG4CXX_ERROR(logger, "RoomChangePayload for unknown user " << user);
return;
}
NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.room());
if (!conv) {
LOG4CXX_ERROR(logger, "RoomChangePayload for unknown conversation " << payload.room());
return;
}

View file

@ -220,6 +220,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
if (CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", false)
&& CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needPassword", true)) {
m_userRegistry->onPasswordInvalid(presence->getFrom());
LOG4CXX_INFO(logger, userkey << ": Tried to login, but is not registered.");
return;
}
res.password = "";

View file

@ -287,7 +287,7 @@ void NetworkPlugin::handleDisconnected(const std::string &user, int error, const
send(message);
}
void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, pbnetwork::StatusType status, const std::string &statusMessage, const std::string &newname) {
void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, pbnetwork::StatusType status, const std::string &statusMessage, const std::string &newname, const std::string &alias) {
pbnetwork::Participant d;
d.set_username(user);
d.set_nickname(nickname);
@ -296,6 +296,7 @@ void NetworkPlugin::handleParticipantChanged(const std::string &user, const std:
d.set_newname(newname);
d.set_status((pbnetwork::StatusType) status);
d.set_statusmessage(statusMessage);
d.set_alias(alias);
std::string message;
d.SerializeToString(&message);