diff --git a/libdino/src/entity/conversation.vala b/libdino/src/entity/conversation.vala index fe9cf9ad..a3a28618 100644 --- a/libdino/src/entity/conversation.vala +++ b/libdino/src/entity/conversation.vala @@ -16,6 +16,7 @@ public class Conversation : Object { public Type type_ { get; set; } public Account account { get; private set; } public Jid counterpart { get; private set; } + public string? nickname { get; private set; } public bool active { get; set; default = false; } private DateTime? _last_active; public DateTime? last_active { @@ -55,6 +56,7 @@ public class Conversation : Object { string? resource = row[db.conversation.resource]; counterpart = Jid.parse(db.get_jid_by_id(row[db.conversation.jid_id])); if (type_ == Conversation.Type.GROUPCHAT_PM) counterpart = counterpart.with_resource(resource); + nickname = type_ == Conversation.Type.GROUPCHAT ? resource : null; active = row[db.conversation.active]; int64? last_active = row[db.conversation.last_active]; if (last_active != null) this.last_active = new DateTime.from_unix_utc(last_active); diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala index ec6316a0..39f7f373 100644 --- a/libdino/src/service/message_processor.vala +++ b/libdino/src/service/message_processor.vala @@ -64,6 +64,7 @@ public class MessageProcessor : StreamInteractionModule, Object { if (message.body == null) return; Entities.Message new_message = create_in_message(account, message); + if (new_message == null) return; determine_message_type(account, message, new_message); } @@ -82,6 +83,23 @@ public class MessageProcessor : StreamInteractionModule, Object { new_message.ourpart = new_message.direction == Entities.Message.DIRECTION_SENT ? message.from : message.to; new_message.stanza = message; + // Slack non-standard behavior + if (account.domainpart.index_of("xmpp.slack.com") == account.domainpart.length - 14) { + if (new_message.counterpart.equals_bare(account.bare_jid)) { + // Ignore messages from us, because we neither know which conversation they belong to, nor can match + // them to one of our send messages because of timestamp mismatches. + return null; + } + if (new_message.direction == Entities.Message.DIRECTION_RECEIVED && message.type_ == "chat" && new_message.body.index_of("["+account.localpart+"] ") == 0) { + // That is the best thing we can do, although allowing for attacks. + new_message.direction = Entities.Message.DIRECTION_SENT; + new_message.body = new_message.body.substring(account.localpart.length + 3); + } + if (message.stanza.get_attribute("ts") != null) { + new_message.time = new DateTime.from_unix_utc((int64) double.parse(message.stanza.get_attribute("ts"))); + } + } + Xep.MessageArchiveManagement.MessageFlag? mam_message_flag = Xep.MessageArchiveManagement.MessageFlag.get_flag(message); if (mam_message_flag != null) new_message.local_time = mam_message_flag.server_time; if (new_message.local_time == null || new_message.local_time.compare(new DateTime.now_utc()) > 0) new_message.local_time = new DateTime.now_utc(); diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala index 4689bdcf..23c234a4 100644 --- a/libdino/src/service/muc_manager.vala +++ b/libdino/src/service/muc_manager.vala @@ -226,9 +226,13 @@ public class MucManager : StreamInteractionModule, Object { private void on_stream_negotiated(Account account, XmppStream stream) { stream.get_module(Xep.Bookmarks.Module.IDENTITY).get_conferences(stream, (stream, conferences) => { - foreach (Xep.Bookmarks.Conference bookmark in conferences) { - if (bookmark.autojoin) { - join(account, bookmark.jid, bookmark.nick, bookmark.password); + if (conferences == null) { + join_all_active(account); + } else { + foreach (Xep.Bookmarks.Conference bookmark in conferences) { + if (bookmark.autojoin) { + join(account, bookmark.jid, bookmark.nick, bookmark.password); + } } } }); @@ -255,6 +259,15 @@ public class MucManager : StreamInteractionModule, Object { } } + private void join_all_active(Account account) { + Gee.List conversations = stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations(account); + foreach (Conversation conversation in conversations) { + if (conversation.type_ == Conversation.Type.GROUPCHAT && conversation.nickname != null) { + join(account, conversation.counterpart, conversation.nickname, null); + } + } + } + private void sync_autojoin_active(Account account, Gee.List conferences) { Gee.List conversations = stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations(account); leave_non_autojoin(account, conferences, conversations);