aboutsummaryrefslogtreecommitdiff
path: root/libdino/src
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2023-01-06 16:14:47 +0100
committerfiaxh <git@lightrise.org>2023-01-11 19:49:03 +0100
commitcb3b19b01deb8460627578b885339e7528411f6f (patch)
treee879305f4f43b0f88c44aeef4c02fde3f101b1e9 /libdino/src
parent0c4aea96ffbc05d6efeb9a83424b872ce7f30d88 (diff)
downloaddino-cb3b19b01deb8460627578b885339e7528411f6f.tar.gz
dino-cb3b19b01deb8460627578b885339e7528411f6f.zip
Support replies and reactions to files
Diffstat (limited to 'libdino/src')
-rw-r--r--libdino/src/service/content_item_store.vala95
-rw-r--r--libdino/src/service/message_processor.vala51
-rw-r--r--libdino/src/service/message_storage.vala4
-rw-r--r--libdino/src/service/reactions.vala78
-rw-r--r--libdino/src/service/replies.vala17
-rw-r--r--libdino/src/service/util.vala1
6 files changed, 154 insertions, 92 deletions
diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala
index 6a9e691f..b3e32cf4 100644
--- a/libdino/src/service/content_item_store.vala
+++ b/libdino/src/service/content_item_store.vala
@@ -44,11 +44,8 @@ public class ContentItemStore : StreamInteractionModule, Object {
Gee.TreeSet<ContentItem> items = new Gee.TreeSet<ContentItem>(ContentItem.compare_func);
foreach (var row in select) {
- int id = row[db.content_item.id];
- int content_type = row[db.content_item.content_type];
- int foreign_id = row[db.content_item.foreign_id];
- DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
- items.add(get_item(conversation, id, content_type, foreign_id, time));
+ ContentItem content_item = get_item_from_row(row, conversation);
+ items.add(content_item);
}
Gee.List<ContentItem> ret = new ArrayList<ContentItem>();
@@ -58,6 +55,14 @@ public class ContentItemStore : StreamInteractionModule, Object {
return ret;
}
+ private ContentItem get_item_from_row(Row row, Conversation conversation) throws Error {
+ int id = row[db.content_item.id];
+ int content_type = row[db.content_item.content_type];
+ int foreign_id = row[db.content_item.foreign_id];
+ DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
+ return get_item(conversation, id, content_type, foreign_id, time);
+ }
+
private ContentItem get_item(Conversation conversation, int id, int content_type, int foreign_id, DateTime time) throws Error {
switch (content_type) {
case 1:
@@ -112,6 +117,86 @@ public class ContentItemStore : StreamInteractionModule, Object {
return item.size > 0 ? item[0] : null;
}
+ public string? get_message_id_for_content_item(Conversation conversation, ContentItem content_item) {
+ Message? message = get_message_for_content_item(conversation, content_item);
+ if (message == null) return null;
+
+ if (conversation.type_ == Conversation.Type.CHAT) {
+ return message.stanza_id;
+ } else {
+ return message.server_id;
+ }
+ }
+
+ public Jid? get_message_sender_for_content_item(Conversation conversation, ContentItem content_item) {
+ Message? message = get_message_for_content_item(conversation, content_item);
+ if (message == null) return null;
+ return message.from;
+ }
+
+ private Message? get_message_for_content_item(Conversation conversation, ContentItem content_item) {
+ FileItem? file_item = content_item as FileItem;
+ if (file_item != null) {
+ if (file_item.file_transfer.provider != 0 || file_item.file_transfer.info == null) return null;
+
+ int message_db_id = int.parse(file_item.file_transfer.info);
+ return stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_db_id, conversation);
+ }
+ MessageItem? message_item = content_item as MessageItem;
+ if (message_item != null) {
+ return message_item.message;
+ }
+ return null;
+ }
+
+ public ContentItem? get_content_item_for_message_id(Conversation conversation, string message_id) {
+ Row? row = get_content_item_row_for_message_id(conversation, message_id);
+ if (row != null) {
+ return get_item_from_row(row, conversation);
+ }
+ return null;
+ }
+
+ public int get_content_item_id_for_message_id(Conversation conversation, string message_id) {
+ Row? row = get_content_item_row_for_message_id(conversation, message_id);
+ if (row != null) {
+ return row[db.content_item.id];
+ }
+ return -1;
+ }
+
+ private Row? get_content_item_row_for_message_id(Conversation conversation, string message_id) {
+ var content_item_row = db.content_item.select();
+
+ Message? message = null;
+ if (conversation.type_ == Conversation.Type.CHAT) {
+ message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(message_id, conversation);
+ } else {
+ message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(message_id, conversation);
+ }
+ if (message == null) return null;
+
+ RowOption file_transfer_row = db.file_transfer.select()
+ .with(db.file_transfer.account_id, "=", conversation.account.id)
+ .with(db.file_transfer.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
+ .with(db.file_transfer.info, "=", message.id.to_string())
+ .order_by(db.file_transfer.time, "DESC")
+ .single().row();
+
+ if (file_transfer_row.is_present()) {
+ content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
+ .with(db.content_item.content_type, "=", 2);
+ } else {
+ content_item_row.with(db.content_item.foreign_id, "=", message.id)
+ .with(db.content_item.content_type, "=", 1);
+ }
+ RowOption content_item_row_option = content_item_row.single().row();
+ if (content_item_row_option.is_present()) {
+ return content_item_row_option.inner;
+ }
+ return null;
+ }
+
public ContentItem? get_latest(Conversation conversation) {
Gee.List<ContentItem> items = get_n_latest(conversation, 1);
if (items.size > 0) {
diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala
index 8d544b45..770ae0a6 100644
--- a/libdino/src/service/message_processor.vala
+++ b/libdino/src/service/message_processor.vala
@@ -425,24 +425,8 @@ public class MessageProcessor : StreamInteractionModule, Object {
new_message.type_ = MessageStanza.TYPE_CHAT;
}
- if (message.quoted_item_id > 0) {
- ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
- if (content_item != null && content_item.type_ == MessageItem.TYPE) {
- Message? quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(((MessageItem) content_item).message.id, conversation);
- if (quoted_message != null) {
- Xep.Replies.set_reply_to(new_message, new Xep.Replies.ReplyTo(quoted_message.from, quoted_message.stanza_id));
-
- string body_with_fallback = "> " + Dino.message_body_without_reply_fallback(quoted_message);
- body_with_fallback = body_with_fallback.replace("\n", "\n> ");
- body_with_fallback += "\n";
- long fallback_length = body_with_fallback.length;
- body_with_fallback += message.body;
- new_message.body = body_with_fallback;
- var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
- Xep.FallbackIndication.set_fallback(new_message, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
- }
- }
- }
+ string? fallback = get_fallback_body_set_infos(message, new_message, conversation);
+ new_message.body = fallback == null ? message.body : fallback + message.body;
build_message_stanza(message, new_message, conversation);
pre_message_send(message, new_message, conversation);
@@ -487,6 +471,37 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
});
}
+
+ public string? get_fallback_body_set_infos(Entities.Message message, MessageStanza new_stanza, Conversation conversation) {
+ if (message.quoted_item_id == 0) return null;
+
+ ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
+ if (content_item == null) return null;
+
+ Jid? quoted_sender = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_sender_for_content_item(conversation, content_item);
+ string? quoted_stanza_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
+ if (quoted_sender != null && quoted_stanza_id != null) {
+ Xep.Replies.set_reply_to(new_stanza, new Xep.Replies.ReplyTo(quoted_sender, quoted_stanza_id));
+ }
+
+ string fallback = "> ";
+
+ if (content_item.type_ == MessageItem.TYPE) {
+ Message? quoted_message = ((MessageItem) content_item).message;
+ fallback += Dino.message_body_without_reply_fallback(quoted_message);
+ fallback = fallback.replace("\n", "\n> ");
+ } else if (content_item.type_ == FileItem.TYPE) {
+ FileTransfer? quoted_file = ((FileItem) content_item).file_transfer;
+ fallback += quoted_file.file_name;
+ }
+ fallback += "\n";
+
+ long fallback_length = fallback.length;
+ var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
+ Xep.FallbackIndication.set_fallback(new_stanza, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
+
+ return fallback;
+ }
}
public abstract class MessageListener : Xmpp.OrderedListener {
diff --git a/libdino/src/service/message_storage.vala b/libdino/src/service/message_storage.vala
index fbdbcf8a..3dadab7b 100644
--- a/libdino/src/service/message_storage.vala
+++ b/libdino/src/service/message_storage.vala
@@ -116,9 +116,7 @@ public class MessageStorage : StreamInteractionModule, Object {
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id)
.outer_join_with(db.reply, db.reply.message_id, db.message.id);
- if (conversation.counterpart.resourcepart == null) {
- query.with_null(db.message.counterpart_resource);
- } else {
+ if (conversation.counterpart.resourcepart != null) {
query.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart);
}
diff --git a/libdino/src/service/reactions.vala b/libdino/src/service/reactions.vala
index fa273f39..f65394bb 100644
--- a/libdino/src/service/reactions.vala
+++ b/libdino/src/service/reactions.vala
@@ -10,7 +10,6 @@ public class Dino.Reactions : StreamInteractionModule, Object {
public string id { get { return IDENTITY.id; } }
public signal void reaction_added(Account account, int content_item_id, Jid jid, string reaction);
-// [Signal(detailed=true)]
public signal void reaction_removed(Account account, int content_item_id, Jid jid, string reaction);
private StreamInteractor stream_interactor;
@@ -35,15 +34,19 @@ public class Dino.Reactions : StreamInteractionModule, Object {
if (!reactions.contains(reaction)) {
reactions.add(reaction);
}
- send_reactions(conversation, content_item, reactions);
- reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ try {
+ send_reactions(conversation, content_item, reactions);
+ reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ } catch (SendError e) {}
}
public void remove_reaction(Conversation conversation, ContentItem content_item, string reaction) {
Gee.List<string> reactions = get_own_reactions(conversation, content_item);
reactions.remove(reaction);
- send_reactions(conversation, content_item, reactions);
- reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ try {
+ send_reactions(conversation, content_item, reactions);
+ reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ } catch (SendError e) {}
}
public Gee.List<ReactionUsers> get_item_reactions(Conversation conversation, ContentItem content_item) {
@@ -80,35 +83,28 @@ public class Dino.Reactions : StreamInteractionModule, Object {
return false;
}
- private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) {
- Message? message = null;
+ private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) throws SendError {
+ string? message_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
+ if (message_id == null) throw new SendError.Misc("No message for content_item");
- FileItem? file_item = content_item as FileItem;
- if (file_item != null) {
- int message_id = int.parse(file_item.file_transfer.info);
- message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_id, conversation);
- }
- MessageItem? message_item = content_item as MessageItem;
- if (message_item != null) {
- message = message_item.message;
- }
+ XmppStream? stream = stream_interactor.get_stream(conversation.account);
+ if (stream == null) throw new SendError.NoStream("");
- if (message == null) {
- return;
- }
+ var reactions_module = stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY);
- XmppStream stream = stream_interactor.get_stream(conversation.account);
- if (conversation.type_ == Conversation.Type.GROUPCHAT || conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
- if (conversation.type_ == Conversation.Type.GROUPCHAT) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "groupchat", message.server_id ?? message.stanza_id, reactions);
- } else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.server_id ?? message.stanza_id, reactions);
- }
+ if (conversation.type_ == Conversation.Type.GROUPCHAT) {
+ reactions_module.send_reaction.begin(stream, conversation.counterpart, "groupchat", message_id, reactions);
// We save the reaction when it gets reflected back to us
+ } else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
+ reactions_module.send_reaction(stream, conversation.counterpart, "chat", message_id, reactions);
} else if (conversation.type_ == Conversation.Type.CHAT) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.stanza_id, reactions);
int64 now_millis = GLib.get_real_time () / 1000;
- save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
+ reactions_module.send_reaction.begin(stream, conversation.counterpart, "chat", message_id, reactions, (_, res) => {
+ try {
+ reactions_module.send_reaction.end(res);
+ save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
+ } catch (SendError e) {}
+ });
}
}
@@ -251,11 +247,11 @@ public class Dino.Reactions : StreamInteractionModule, Object {
Message reaction_message = yield stream_interactor.get_module(MessageProcessor.IDENTITY).parse_message_stanza(account, stanza);
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message);
- Message? message = get_message_for_reaction(conversation, message_id);
+ int content_item_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_id_for_message_id(conversation, message_id);
var reaction_info = new ReactionInfo() { account=account, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() };
- if (message != null) {
- process_reaction_for_message(message.id, reaction_info);
+ if (content_item_id != -1) {
+ process_reaction_for_message(content_item_id, reaction_info);
return;
}
@@ -317,30 +313,12 @@ public class Dino.Reactions : StreamInteractionModule, Object {
}
}
- private void process_reaction_for_message(int message_db_id, ReactionInfo reaction_info) {
+ private void process_reaction_for_message(int content_item_id, ReactionInfo reaction_info) {
Account account = reaction_info.account;
MessageStanza stanza = reaction_info.stanza;
Jid from_jid = reaction_info.from_jid;
Gee.List<string> reactions = reaction_info.reactions;
- RowOption file_transfer_row = db.file_transfer.select()
- .with(db.file_transfer.account_id, "=", account.id)
- .with(db.file_transfer.info, "=", message_db_id.to_string())
- .single().row(); // TODO better
-
- var content_item_row = db.content_item.select();
-
- if (file_transfer_row.is_present()) {
- content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
- .with(db.content_item.content_type, "=", 2);
- } else {
- content_item_row.with(db.content_item.foreign_id, "=", message_db_id)
- .with(db.content_item.content_type, "=", 1);
- }
- var content_item_row_opt = content_item_row.single().row();
- if (!content_item_row_opt.is_present()) return;
- int content_item_id = content_item_row_opt[db.content_item.id];
-
// Get reaction time
DateTime? reaction_time = null;
DelayedDelivery.MessageFlag? delayed_message_flag = DelayedDelivery.MessageFlag.get_flag(stanza);
diff --git a/libdino/src/service/replies.vala b/libdino/src/service/replies.vala
index 6a9bced4..97db70ee 100644
--- a/libdino/src/service/replies.vala
+++ b/libdino/src/service/replies.vala
@@ -77,22 +77,7 @@ public class Dino.Replies : StreamInteractionModule, Object {
Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza);
if (reply_to == null) return;
- Message? quoted_message = null;
- if (conversation.type_ == Conversation.Type.GROUPCHAT) {
- quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(reply_to.to_message_id, conversation);
- } else {
- quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(reply_to.to_message_id, conversation);
- }
- if (quoted_message == null) {
- db.reply.upsert()
- .value(db.reply.message_id, message.id, true)
- .value(db.reply.quoted_message_stanza_id, reply_to.to_message_id)
- .value(db.reply.quoted_message_from, reply_to.to_jid.to_string())
- .perform();
- return;
- }
-
- ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_foreign(conversation, 1, quoted_message.id);
+ ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message_id(conversation, reply_to.to_message_id);
if (quoted_content_item == null) return;
set_message_is_reply_to(message, quoted_content_item);
diff --git a/libdino/src/service/util.vala b/libdino/src/service/util.vala
index 3cbb48d9..1d04ffcf 100644
--- a/libdino/src/service/util.vala
+++ b/libdino/src/service/util.vala
@@ -1,4 +1,5 @@
using Dino.Entities;
+using Qlite;
namespace Dino {