aboutsummaryrefslogtreecommitdiff
path: root/client/src/service
diff options
context:
space:
mode:
authorfiaxh <git@mx.ax.lt>2017-03-09 15:34:32 +0100
committerfiaxh <git@mx.ax.lt>2017-03-09 15:45:03 +0100
commit5fc0435cc1227bf445d06a3931343020faaecd10 (patch)
tree329041d3b2545fc445e9f175d3d5fff755fd110b /client/src/service
parentb1e6e51c4f79f57f0a01b183ef185408fb22cc36 (diff)
downloaddino-5fc0435cc1227bf445d06a3931343020faaecd10.tar.gz
dino-5fc0435cc1227bf445d06a3931343020faaecd10.zip
Save unsent messages (acc offline etc) and send later; don't send pgp messages if pgp error
Diffstat (limited to 'client/src/service')
-rw-r--r--client/src/service/chat_interaction.vala4
-rw-r--r--client/src/service/conversation_manager.vala13
-rw-r--r--client/src/service/database.vala55
-rw-r--r--client/src/service/message_manager.vala113
-rw-r--r--client/src/service/muc_manager.vala4
-rw-r--r--client/src/service/stream_interactor.vala2
6 files changed, 117 insertions, 74 deletions
diff --git a/client/src/service/chat_interaction.vala b/client/src/service/chat_interaction.vala
index ed805a93..cd6907fa 100644
--- a/client/src/service/chat_interaction.vala
+++ b/client/src/service/chat_interaction.vala
@@ -47,7 +47,7 @@ public class ChatInteraction : StreamInteractionModule, Object {
public void on_message_entered(Conversation conversation) {
if (Settings.instance().send_read) {
- if (!last_input_interaction.has_key(conversation) && conversation.type_ != Conversation.TYPE_GROUPCHAT) {
+ if (!last_input_interaction.has_key(conversation) && conversation.type_ != Conversation.Type.GROUPCHAT) {
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_COMPOSING);
}
}
@@ -82,7 +82,7 @@ public class ChatInteraction : StreamInteractionModule, Object {
}
private void check_send_read() {
- if (selected_conversation == null || selected_conversation.type_ == Conversation.TYPE_GROUPCHAT) return;
+ if (selected_conversation == null || selected_conversation.type_ == Conversation.Type.GROUPCHAT) return;
Entities.Message? message = MessageManager.get_instance(stream_interactor).get_last_message(selected_conversation);
if (message != null && message.direction == Entities.Message.DIRECTION_RECEIVED &&
message.stanza != null && !message.equals(selected_conversation.read_up_to)) {
diff --git a/client/src/service/conversation_manager.vala b/client/src/service/conversation_manager.vala
index 5337f007..716c9b39 100644
--- a/client/src/service/conversation_manager.vala
+++ b/client/src/service/conversation_manager.vala
@@ -27,6 +27,7 @@ public class ConversationManager : StreamInteractionModule, Object {
stream_interactor.account_added.connect(on_account_added);
MucManager.get_instance(stream_interactor).groupchat_joined.connect(on_groupchat_joined);
MessageManager.get_instance(stream_interactor).pre_message_received.connect(on_message_received);
+ MessageManager.get_instance(stream_interactor).message_sent.connect(on_message_sent);
}
public Conversation? get_conversation(Jid jid, Account account) {
@@ -37,12 +38,12 @@ public class ConversationManager : StreamInteractionModule, Object {
}
public Conversation get_add_conversation(Jid jid, Account account) {
- ensure_add_conversation(jid, account, Conversation.TYPE_CHAT);
+ ensure_add_conversation(jid, account, Conversation.Type.CHAT);
return get_conversation(jid, account);
}
public void ensure_start_conversation(Jid jid, Account account) {
- ensure_add_conversation(jid, account, Conversation.TYPE_CHAT);
+ ensure_add_conversation(jid, account, Conversation.Type.CHAT);
Conversation? conversation = get_conversation(jid, account);
if (conversation != null) {
conversation.last_active = new DateTime.now_utc();
@@ -73,12 +74,16 @@ public class ConversationManager : StreamInteractionModule, Object {
ensure_start_conversation(conversation.counterpart, conversation.account);
}
+ private void on_message_sent(Entities.Message message, Conversation conversation) {
+ conversation.last_active = message.time;
+ }
+
private void on_groupchat_joined(Account account, Jid jid, string nick) {
- ensure_add_conversation(jid, account, Conversation.TYPE_GROUPCHAT);
+ ensure_add_conversation(jid, account, Conversation.Type.GROUPCHAT);
ensure_start_conversation(jid, account);
}
- private void ensure_add_conversation(Jid jid, Account account, int type) {
+ private void ensure_add_conversation(Jid jid, Account account, Conversation.Type type) {
if (conversations.has_key(account) && !conversations[account].has_key(jid)) {
Conversation conversation = new Conversation(jid, account);
conversation.type_ = type;
diff --git a/client/src/service/database.vala b/client/src/service/database.vala
index 6428d83f..13be6222 100644
--- a/client/src/service/database.vala
+++ b/client/src/service/database.vala
@@ -36,11 +36,11 @@ public class Database : Qlite.Database {
public class MessageTable : Table {
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
public Column<string> stanza_id = new Column.Text("stanza_id");
- public Column<int> account_id = new Column.Integer("account_id");
- public Column<int> counterpart_id = new Column.Integer("counterpart_id");
+ public Column<int> account_id = new Column.Integer("account_id") { not_null = true };
+ public Column<int> counterpart_id = new Column.Integer("counterpart_id") { not_null = true };
public Column<string> counterpart_resource = new Column.Text("counterpart_resource");
public Column<string> our_resource = new Column.Text("our_resource");
- public Column<bool> direction = new Column.BoolInt("direction");
+ public Column<bool> direction = new Column.BoolInt("direction") { not_null = true };
public Column<int> type_ = new Column.Integer("type");
public Column<long> time = new Column.Long("time");
public Column<long> local_time = new Column.Long("local_time");
@@ -205,24 +205,20 @@ public class Database : Qlite.Database {
}
public void add_message(Message new_message, Account account) {
- if (new_message.body == null || new_message.stanza_id == null) {
- return;
- }
-
- new_message.id = (int) message.insert()
- .value(message.stanza_id, new_message.stanza_id)
- .value(message.account_id, new_message.account.id)
- .value(message.counterpart_id, get_jid_id(new_message.counterpart))
- .value(message.counterpart_resource, new_message.counterpart.resourcepart)
- .value(message.our_resource, new_message.ourpart.resourcepart)
- .value(message.direction, new_message.direction)
- .value(message.type_, new_message.type_)
- .value(message.time, (long) new_message.time.to_unix())
- .value(message.local_time, (long) new_message.local_time.to_unix())
- .value(message.body, new_message.body)
- .value(message.encryption, new_message.encryption)
- .value(message.marked, new_message.marked)
- .perform();
+ InsertBuilder builder = message.insert()
+ .value(message.account_id, new_message.account.id)
+ .value(message.counterpart_id, get_jid_id(new_message.counterpart))
+ .value(message.counterpart_resource, new_message.counterpart.resourcepart)
+ .value(message.our_resource, new_message.ourpart.resourcepart)
+ .value(message.direction, new_message.direction)
+ .value(message.type_, new_message.type_)
+ .value(message.time, (long) new_message.time.to_unix())
+ .value(message.local_time, (long) new_message.local_time.to_unix())
+ .value(message.body, new_message.body)
+ .value(message.encryption, new_message.encryption)
+ .value(message.marked, new_message.marked);
+ if (new_message.stanza_id != null) builder.value(message.stanza_id, new_message.stanza_id);
+ new_message.id = (int) builder.perform();
if (new_message.real_jid != null) {
real_jid.insert()
@@ -288,6 +284,14 @@ public class Database : Qlite.Database {
return ret;
}
+ public Gee.List<Message> get_unsend_messages(Account account) {
+ Gee.List<Message> ret = new ArrayList<Message>();
+ foreach (Row row in message.select().with(message.marked, "=", (int) Message.Marked.UNSENT)) {
+ ret.add(get_message_from_row(row));
+ }
+ return ret;
+ }
+
public bool contains_message(Message query_message, Account account) {
int jid_id = get_jid_id(query_message.counterpart);
return message.select()
@@ -295,6 +299,9 @@ public class Database : Qlite.Database {
.with(message.stanza_id, "=", query_message.stanza_id)
.with(message.counterpart_id, "=", jid_id)
.with(message.counterpart_resource, "=", query_message.counterpart.resourcepart)
+ .with(message.body, "=", query_message.body)
+ .with(message.time, "<", (long) query_message.time.add_minutes(1).to_unix())
+ .with(message.time, ">", (long) query_message.time.add_minutes(-1).to_unix())
.count() > 0;
}
@@ -332,6 +339,8 @@ public class Database : Qlite.Database {
new_message.marked = (Message.Marked) row[message.marked];
new_message.encryption = (Message.Encryption) row[message.encryption];
new_message.real_jid = get_real_jid_for_message(new_message);
+
+ new_message.notify.connect(on_message_update);
return new_message;
}
@@ -386,8 +395,8 @@ public class Database : Qlite.Database {
new_conversation.active = row[conversation.active];
int64? last_active = row[conversation.last_active];
if (last_active != null) new_conversation.last_active = new DateTime.from_unix_utc(last_active);
- new_conversation.type_ = row[conversation.type_];
- new_conversation.encryption = row[conversation.encryption];
+ new_conversation.type_ = (Conversation.Type) row[conversation.type_];
+ new_conversation.encryption = (Conversation.Encryption) row[conversation.encryption];
int? read_up_to = row[conversation.read_up_to];
if (read_up_to != null) new_conversation.read_up_to = get_message_by_id(read_up_to);
diff --git a/client/src/service/message_manager.vala b/client/src/service/message_manager.vala
index a268e619..054db518 100644
--- a/client/src/service/message_manager.vala
+++ b/client/src/service/message_manager.vala
@@ -6,7 +6,7 @@ using Dino.Entities;
namespace Dino {
public class MessageManager : StreamInteractionModule, Object {
- public const string id = "message_manager";
+ public const string ID = "message_manager";
public signal void pre_message_received(Entities.Message message, Conversation conversation);
public signal void message_received(Entities.Message message, Conversation conversation);
@@ -25,46 +25,16 @@ public class MessageManager : StreamInteractionModule, Object {
this.stream_interactor = stream_interactor;
this.db = db;
stream_interactor.account_added.connect(on_account_added);
+ stream_interactor.connection_manager.connection_state_changed.connect((account, state) => {
+ if (state == ConnectionManager.ConnectionState.CONNECTED) send_unsent_messages(account);
+ });
}
public void send_message(string text, Conversation conversation) {
- Entities.Message message = new Entities.Message();
- message.account = conversation.account;
- message.body = text;
- message.time = new DateTime.now_utc();
- message.local_time = new DateTime.now_utc();
- message.direction = Entities.Message.DIRECTION_SENT;
- message.counterpart = conversation.counterpart;
- message.ourpart = new Jid(conversation.account.bare_jid.to_string() + "/" + conversation.account.resourcepart);
-
- Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
-
- if (stream != null) {
- Xmpp.Message.Stanza new_message = new Xmpp.Message.Stanza();
- new_message.to = message.counterpart.to_string();
- new_message.body = message.body;
- if (conversation.type_ == Conversation.TYPE_GROUPCHAT) {
- new_message.type_ = Xmpp.Message.Stanza.TYPE_GROUPCHAT;
- } else {
- new_message.type_ = Xmpp.Message.Stanza.TYPE_CHAT;
- }
- if (conversation.encryption == Conversation.ENCRYPTION_PGP) {
- string? key_id = PgpManager.get_instance(stream_interactor).get_key_id(conversation.account, message.counterpart);
- if (key_id != null) {
- bool encrypted = Xep.Pgp.Module.get_module(stream).encrypt(new_message, key_id);
- if (encrypted) message.encryption = Entities.Message.Encryption.PGP;
- }
- }
- Xmpp.Message.Module.get_module(stream).send_message(stream, new_message);
- message.stanza_id = new_message.id;
- message.stanza = new_message;
- db.add_message(message, conversation.account);
- } else {
- // save for resend
- }
-
- conversation.last_active = message.time;
+ Entities.Message message = create_out_message(text, conversation);
add_message(message, conversation);
+ db.add_message(message, conversation.account);
+ send_xmpp_message(message, conversation);
message_sent(message, conversation);
}
@@ -97,17 +67,26 @@ public class MessageManager : StreamInteractionModule, Object {
}
public string get_id() {
- return id;
+ return ID;
}
public static MessageManager? get_instance(StreamInteractor stream_interactor) {
- return (MessageManager) stream_interactor.get_module(id);
+ return (MessageManager) stream_interactor.get_module(ID);
}
private void on_account_added(Account account) {
stream_interactor.module_manager.message_modules[account].received_message.connect( (stream, message) => {
on_message_received(account, message);
});
+ stream_interactor.stream_negotiated.connect(send_unsent_messages);
+ }
+
+ private void send_unsent_messages(Account account) {
+ Gee.List<Entities.Message> unsend_messages = db.get_unsend_messages(account);
+ foreach (Entities.Message message in unsend_messages) {
+ Conversation conversation = ConversationManager.get_instance(stream_interactor).get_conversation(message.counterpart, account);
+ send_xmpp_message(message, conversation, true);
+ }
}
private void on_message_received(Account account, Xmpp.Message.Stanza message) {
@@ -128,10 +107,8 @@ public class MessageManager : StreamInteractionModule, Object {
new_message.body = message.body;
new_message.stanza = message;
new_message.set_type_string(message.type_);
- new_message.time = Xep.DelayedDelivery.Module.get_send_time(message);
- if (new_message.time == null) {
- new_message.time = new DateTime.now_utc();
- }
+ Xep.DelayedDelivery.MessageFlag? deleyed_delivery_flag = Xep.DelayedDelivery.MessageFlag.get_flag(message);
+ new_message.time = deleyed_delivery_flag != null ? deleyed_delivery_flag.datetime : new DateTime.now_utc();
new_message.local_time = new DateTime.now_utc();
if (Xep.Pgp.MessageFlag.get_flag(message) != null) {
new_message.encryption = Entities.Message.Encryption.PGP;
@@ -161,6 +138,56 @@ public class MessageManager : StreamInteractionModule, Object {
}
messages[conversation].add(message);
}
+
+ private Entities.Message create_out_message(string text, Conversation conversation) {
+ Entities.Message message = new Entities.Message();
+ message.stanza_id = UUID.generate_random_unparsed();
+ message.account = conversation.account;
+ message.body = text;
+ message.time = new DateTime.now_utc();
+ message.local_time = new DateTime.now_utc();
+ message.direction = Entities.Message.DIRECTION_SENT;
+ message.counterpart = conversation.counterpart;
+ message.ourpart = new Jid(conversation.account.bare_jid.to_string() + "/" + conversation.account.resourcepart);
+
+ if (conversation.encryption == Conversation.Encryption.PGP) {
+ message.encryption = Entities.Message.Encryption.PGP;
+ }
+ return message;
+ }
+
+ private void send_xmpp_message(Entities.Message message, Conversation conversation, bool delayed = false) {
+ Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
+ message.marked = Entities.Message.Marked.NONE;
+ if (stream != null) {
+ Xmpp.Message.Stanza new_message = new Xmpp.Message.Stanza(message.stanza_id);
+ new_message.to = message.counterpart.to_string();
+ new_message.body = message.body;
+ if (conversation.type_ == Conversation.Type.GROUPCHAT) {
+ new_message.type_ = Xmpp.Message.Stanza.TYPE_GROUPCHAT;
+ } else {
+ new_message.type_ = Xmpp.Message.Stanza.TYPE_CHAT;
+ }
+ if (message.encryption == Entities.Message.Encryption.PGP) {
+ string? key_id = PgpManager.get_instance(stream_interactor).get_key_id(conversation.account, message.counterpart);
+ if (key_id != null) {
+ bool encrypted = Xep.Pgp.Module.get_module(stream).encrypt(new_message, key_id);
+ if (!encrypted) {
+ message.marked = Entities.Message.Marked.WONTSEND;
+ return;
+ }
+ }
+ }
+ if (delayed) {
+ Xmpp.Xep.DelayedDelivery.Module.get_module(stream).set_message_delay(new_message, message.time);
+ }
+ Xmpp.Message.Module.get_module(stream).send_message(stream, new_message);
+ message.stanza_id = new_message.id;
+ message.stanza = new_message;
+ } else {
+ message.marked = Entities.Message.Marked.UNSENT;
+ }
+ }
}
} \ No newline at end of file
diff --git a/client/src/service/muc_manager.vala b/client/src/service/muc_manager.vala
index 8f6339a5..be23d391 100644
--- a/client/src/service/muc_manager.vala
+++ b/client/src/service/muc_manager.vala
@@ -66,7 +66,7 @@ public class MucManager : StreamInteractionModule, Object {
public bool is_groupchat(Jid jid, Account account) {
Conversation? conversation = ConversationManager.get_instance(stream_interactor).get_conversation(jid, account);
- return !jid.is_full() && conversation != null && conversation.type_ == Conversation.TYPE_GROUPCHAT;
+ return !jid.is_full() && conversation != null && conversation.type_ == Conversation.Type.GROUPCHAT;
}
public bool is_groupchat_occupant(Jid jid, Account account) {
@@ -162,7 +162,7 @@ public class MucManager : StreamInteractionModule, Object {
}
private void on_pre_message_received(Entities.Message message, Conversation conversation) {
- if (conversation.type_ != Conversation.TYPE_GROUPCHAT) return;
+ if (conversation.type_ != Conversation.Type.GROUPCHAT) return;
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
if (stream == null) return;
if (Xep.DelayedDelivery.MessageFlag.get_flag(message.stanza) == null) {
diff --git a/client/src/service/stream_interactor.vala b/client/src/service/stream_interactor.vala
index 56591cf0..f3859e3b 100644
--- a/client/src/service/stream_interactor.vala
+++ b/client/src/service/stream_interactor.vala
@@ -4,6 +4,7 @@ using Xmpp;
using Dino.Entities;
namespace Dino {
+
public class StreamInteractor {
public signal void account_added(Account account);
@@ -65,4 +66,5 @@ public class StreamInteractor {
public interface StreamInteractionModule : Object {
internal abstract string get_id();
}
+
} \ No newline at end of file