Handle MUC private messages
This commit is contained in:
parent
7d2f995a09
commit
22adbd38dc
|
@ -6,7 +6,8 @@ public class Conversation : Object {
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
CHAT,
|
CHAT,
|
||||||
GROUPCHAT
|
GROUPCHAT,
|
||||||
|
GROUPCHAT_PM
|
||||||
}
|
}
|
||||||
|
|
||||||
public int id { get; set; }
|
public int id { get; set; }
|
||||||
|
@ -30,8 +31,8 @@ public class Conversation : Object {
|
||||||
private Database? db;
|
private Database? db;
|
||||||
|
|
||||||
public Conversation(Jid jid, Account account, Type type) {
|
public Conversation(Jid jid, Account account, Type type) {
|
||||||
this.counterpart = jid;
|
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
this.counterpart = jid;
|
||||||
this.type_ = type;
|
this.type_ = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +40,10 @@ public class Conversation : Object {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
|
||||||
id = row[db.conversation.id];
|
id = row[db.conversation.id];
|
||||||
counterpart = new Jid(db.get_jid_by_id(row[db.conversation.jid_id]));
|
|
||||||
account = db.get_account_by_id(row[db.conversation.account_id]);
|
account = db.get_account_by_id(row[db.conversation.account_id]);
|
||||||
|
string? resource = row[db.conversation.resource];
|
||||||
|
string jid = db.get_jid_by_id(row[db.conversation.jid_id]);
|
||||||
|
counterpart = resource != null ? new Jid.with_resource(jid, resource) : new Jid(jid);
|
||||||
active = row[db.conversation.active];
|
active = row[db.conversation.active];
|
||||||
int64? last_active = row[db.conversation.last_active];
|
int64? last_active = row[db.conversation.last_active];
|
||||||
if (last_active != null) this.last_active = new DateTime.from_unix_local(last_active);
|
if (last_active != null) this.last_active = new DateTime.from_unix_local(last_active);
|
||||||
|
@ -55,12 +58,15 @@ public class Conversation : Object {
|
||||||
public void persist(Database db) {
|
public void persist(Database db) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
var insert = db.conversation.insert()
|
var insert = db.conversation.insert()
|
||||||
.value(db.conversation.jid_id, db.get_jid_id(counterpart))
|
|
||||||
.value(db.conversation.account_id, account.id)
|
.value(db.conversation.account_id, account.id)
|
||||||
|
.value(db.conversation.jid_id, db.get_jid_id(counterpart))
|
||||||
.value(db.conversation.type_, type_)
|
.value(db.conversation.type_, type_)
|
||||||
.value(db.conversation.encryption, encryption)
|
.value(db.conversation.encryption, encryption)
|
||||||
//.value(conversation.read_up_to, new_conversation.read_up_to)
|
//.value(conversation.read_up_to, new_conversation.read_up_to)
|
||||||
.value(db.conversation.active, active);
|
.value(db.conversation.active, active);
|
||||||
|
if (counterpart.is_full()) {
|
||||||
|
insert.value(db.conversation.resource, counterpart.resourcepart);
|
||||||
|
}
|
||||||
if (last_active != null) {
|
if (last_active != null) {
|
||||||
insert.value(db.conversation.last_active, (long) last_active.to_unix());
|
insert.value(db.conversation.last_active, (long) last_active.to_unix());
|
||||||
}
|
}
|
||||||
|
@ -90,7 +96,12 @@ public class Conversation : Object {
|
||||||
case "encryption":
|
case "encryption":
|
||||||
update.set(db.conversation.encryption, encryption); break;
|
update.set(db.conversation.encryption, encryption); break;
|
||||||
case "read-up-to":
|
case "read-up-to":
|
||||||
update.set(db.conversation.read_up_to, read_up_to.id); break;
|
if (read_up_to != null) {
|
||||||
|
update.set(db.conversation.read_up_to, read_up_to.id);
|
||||||
|
} else {
|
||||||
|
update.set_null(db.conversation.read_up_to);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "active":
|
case "active":
|
||||||
update.set(db.conversation.active, active); break;
|
update.set(db.conversation.active, active); break;
|
||||||
case "last-active":
|
case "last-active":
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class Dino.Entities.Jid : Object {
|
||||||
|
|
||||||
public Jid.with_resource(string bare_jid, string resource) {
|
public Jid.with_resource(string bare_jid, string resource) {
|
||||||
Jid? parsed = Jid.parse(bare_jid);
|
Jid? parsed = Jid.parse(bare_jid);
|
||||||
this.components(parsed.localpart, parsed.domainpart, resourcepart);
|
this.components(parsed.localpart, parsed.domainpart, resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Jid.components(string? localpart, string domainpart, string? resourcepart) {
|
public Jid.components(string? localpart, string domainpart, string? resourcepart) {
|
||||||
|
|
|
@ -20,8 +20,8 @@ public class Message : Object {
|
||||||
ERROR,
|
ERROR,
|
||||||
CHAT,
|
CHAT,
|
||||||
GROUPCHAT,
|
GROUPCHAT,
|
||||||
HEADLINE,
|
GROUPCHAT_PM,
|
||||||
NORMAL
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? id { get; set; }
|
public int? id { get; set; }
|
||||||
|
@ -36,7 +36,7 @@ public class Message : Object {
|
||||||
}
|
}
|
||||||
public bool direction { get; set; }
|
public bool direction { get; set; }
|
||||||
public string? real_jid { get; set; }
|
public string? real_jid { get; set; }
|
||||||
public Type type_ { get; set; }
|
public Type type_ { get; set; default = Type.UNKNOWN; }
|
||||||
public string? body { get; set; }
|
public string? body { get; set; }
|
||||||
public string? stanza_id { get; set; }
|
public string? stanza_id { get; set; }
|
||||||
public DateTime? time { get; set; }
|
public DateTime? time { get; set; }
|
||||||
|
@ -48,10 +48,9 @@ public class Message : Object {
|
||||||
|
|
||||||
private Database? db;
|
private Database? db;
|
||||||
|
|
||||||
public Message(string? body, Type type) {
|
public Message(string? body) {
|
||||||
this.id = -1;
|
this.id = -1;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.type_ = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message.from_row(Database db, Qlite.Row row) {
|
public Message.from_row(Database db, Qlite.Row row) {
|
||||||
|
@ -107,8 +106,6 @@ public class Message : Object {
|
||||||
type_ = Type.CHAT; break;
|
type_ = Type.CHAT; break;
|
||||||
case Xmpp.Message.Stanza.TYPE_GROUPCHAT:
|
case Xmpp.Message.Stanza.TYPE_GROUPCHAT:
|
||||||
type_ = Type.GROUPCHAT; break;
|
type_ = Type.GROUPCHAT; break;
|
||||||
default:
|
|
||||||
type_ = Type.NORMAL; break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ConversationManager : StreamInteractionModule, Object {
|
||||||
stream_interactor.get_module(MessageManager.IDENTITY).message_sent.connect(on_message_sent);
|
stream_interactor.get_module(MessageManager.IDENTITY).message_sent.connect(on_message_sent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Conversation create_conversation(Jid jid, Account account, Conversation.Type type) {
|
public Conversation create_conversation(Jid jid, Account account, Conversation.Type? type = null) {
|
||||||
assert(conversations.has_key(account));
|
assert(conversations.has_key(account));
|
||||||
if (conversations[account].has_key(jid)) {
|
if (conversations[account].has_key(jid)) {
|
||||||
return conversations[account][jid];
|
return conversations[account][jid];
|
||||||
|
@ -43,6 +43,26 @@ public class ConversationManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Conversation? get_conversation_for_message(Entities.Message message) {
|
||||||
|
if (message.type_ == Entities.Message.Type.CHAT) {
|
||||||
|
return create_conversation(message.counterpart.bare_jid, message.account, Conversation.Type.CHAT);
|
||||||
|
} else if (message.type_ == Entities.Message.Type.GROUPCHAT) {
|
||||||
|
return create_conversation(message.counterpart.bare_jid, message.account, Conversation.Type.GROUPCHAT);
|
||||||
|
} else if (message.type_ == Entities.Message.Type.GROUPCHAT_PM) {
|
||||||
|
return create_conversation(message.counterpart, message.account, Conversation.Type.GROUPCHAT_PM);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gee.List<Conversation> get_conversations_for_presence(Show show, Account account) {
|
||||||
|
Gee.List<Conversation> ret = new ArrayList<Conversation>(Conversation.equals_func);
|
||||||
|
Conversation? bare_conversation = get_conversation(show.jid, account);
|
||||||
|
if (bare_conversation != null) ret.add(bare_conversation);
|
||||||
|
Conversation? full_conversation = get_conversation(show.jid.bare_jid, account);
|
||||||
|
if (full_conversation != null) ret.add(full_conversation);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public Conversation? get_conversation(Jid jid, Account account) {
|
public Conversation? get_conversation(Jid jid, Account account) {
|
||||||
if (conversations.has_key(account)) {
|
if (conversations.has_key(account)) {
|
||||||
return conversations[account][jid];
|
return conversations[account][jid];
|
||||||
|
@ -77,7 +97,7 @@ public class ConversationManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_account_added(Account account) {
|
private void on_account_added(Account account) {
|
||||||
conversations[account] = new HashMap<Jid, Conversation>(Jid.hash_bare_func, Jid.equals_bare_func);
|
conversations[account] = new HashMap<Jid, Conversation>(Jid.hash_func, Jid.equals_func);
|
||||||
foreach (Conversation conversation in db.get_conversations(account)) {
|
foreach (Conversation conversation in db.get_conversations(account)) {
|
||||||
add_conversation(conversation);
|
add_conversation(conversation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ public class Database : Qlite.Database {
|
||||||
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
public Column<int> id = new Column.Integer("id") { primary_key = true, auto_increment = true };
|
||||||
public Column<int> account_id = new Column.Integer("account_id") { not_null = true };
|
public Column<int> account_id = new Column.Integer("account_id") { not_null = true };
|
||||||
public Column<int> jid_id = new Column.Integer("jid_id") { not_null = true };
|
public Column<int> jid_id = new Column.Integer("jid_id") { not_null = true };
|
||||||
|
public Column<string> resource = new Column.Text("resource");
|
||||||
public Column<bool> active = new Column.BoolInt("active");
|
public Column<bool> active = new Column.BoolInt("active");
|
||||||
public Column<long> last_active = new Column.Long("last_active");
|
public Column<long> last_active = new Column.Long("last_active");
|
||||||
public Column<int> type_ = new Column.Integer("type");
|
public Column<int> type_ = new Column.Integer("type");
|
||||||
|
@ -87,7 +88,7 @@ public class Database : Qlite.Database {
|
||||||
|
|
||||||
internal ConversationTable(Database db) {
|
internal ConversationTable(Database db) {
|
||||||
base(db, "conversation");
|
base(db, "conversation");
|
||||||
init({id, account_id, jid_id, active, last_active, type_, encryption, read_up_to});
|
init({id, account_id, jid_id, resource, active, last_active, type_, encryption, read_up_to});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,12 +165,18 @@ public class Database : Qlite.Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<Message> get_messages(Jid jid, Account account, int count, Message? before) {
|
public Gee.List<Message> get_messages(Jid jid, Account account, Message.Type? type, int count, Message? before) {
|
||||||
QueryBuilder select = message.select()
|
QueryBuilder select = message.select()
|
||||||
.with(message.counterpart_id, "=", get_jid_id(jid))
|
.with(message.counterpart_id, "=", get_jid_id(jid))
|
||||||
.with(message.account_id, "=", account.id)
|
.with(message.account_id, "=", account.id)
|
||||||
.order_by(message.id, "DESC")
|
.order_by(message.id, "DESC")
|
||||||
.limit(count);
|
.limit(count);
|
||||||
|
if (jid.resourcepart != null) {
|
||||||
|
select.with(message.counterpart_resource, "=", jid.resourcepart);
|
||||||
|
}
|
||||||
|
if (type != null) {
|
||||||
|
select.with(message.type_, "=", (int) type);
|
||||||
|
}
|
||||||
if (before != null) {
|
if (before != null) {
|
||||||
select.with(message.time, "<", (long) before.time.to_unix());
|
select.with(message.time, "<", (long) before.time.to_unix());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,11 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
|
|
||||||
public Gee.List<Entities.Message>? get_messages(Conversation conversation, int count = 50) {
|
public Gee.List<Entities.Message>? get_messages(Conversation conversation, int count = 50) {
|
||||||
if (messages.has_key(conversation) && messages[conversation].size > 0) {
|
if (messages.has_key(conversation) && messages[conversation].size > 0) {
|
||||||
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, count, messages[conversation][0]);
|
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, get_message_type_for_conversation(conversation), count, messages[conversation][0]);
|
||||||
db_messages.add_all(messages[conversation]);
|
db_messages.add_all(messages[conversation]);
|
||||||
return db_messages;
|
return db_messages;
|
||||||
} else {
|
} else {
|
||||||
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, count, null);
|
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, get_message_type_for_conversation(conversation), count, null);
|
||||||
return db_messages;
|
return db_messages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
if (messages.has_key(conversation) && messages[conversation].size > 0) {
|
if (messages.has_key(conversation) && messages[conversation].size > 0) {
|
||||||
return messages[conversation][messages[conversation].size - 1];
|
return messages[conversation][messages[conversation].size - 1];
|
||||||
} else {
|
} else {
|
||||||
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, 1, null);
|
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, get_message_type_for_conversation(conversation), 1, null);
|
||||||
if (db_messages.size >= 1) {
|
if (db_messages.size >= 1) {
|
||||||
return db_messages[0];
|
return db_messages[0];
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,22 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Gee.List<Entities.Message>? get_messages_before(Conversation? conversation, Entities.Message before) {
|
public Gee.List<Entities.Message>? get_messages_before(Conversation? conversation, Entities.Message before) {
|
||||||
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, 20, before);
|
Gee.List<Entities.Message> db_messages = db.get_messages(conversation.counterpart, conversation.account, get_message_type_for_conversation(conversation), 20, before);
|
||||||
return db_messages;
|
return db_messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Entities.Message.Type get_message_type_for_conversation(Conversation conversation) {
|
||||||
|
switch (conversation.type_) {
|
||||||
|
case Conversation.Type.CHAT:
|
||||||
|
return Entities.Message.Type.CHAT;
|
||||||
|
case Conversation.Type.GROUPCHAT:
|
||||||
|
return Entities.Message.Type.GROUPCHAT;
|
||||||
|
case Conversation.Type.GROUPCHAT_PM:
|
||||||
|
return Entities.Message.Type.GROUPCHAT_PM;
|
||||||
|
}
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
private void on_account_added(Account account) {
|
private void on_account_added(Account account) {
|
||||||
stream_interactor.module_manager.get_module(account, Xmpp.Message.Module.IDENTITY).received_message.connect( (stream, message) => {
|
stream_interactor.module_manager.get_module(account, Xmpp.Message.Module.IDENTITY).received_message.connect( (stream, message) => {
|
||||||
on_message_received(account, message);
|
on_message_received(account, message);
|
||||||
|
@ -88,8 +100,15 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
private void on_message_received(Account account, Xmpp.Message.Stanza message) {
|
private void on_message_received(Account account, Xmpp.Message.Stanza message) {
|
||||||
if (message.body == null) return;
|
if (message.body == null) return;
|
||||||
|
|
||||||
Entities.Message.Type type_ = message.type_ == Xmpp.Message.Stanza.TYPE_GROUPCHAT ? Entities.Message.Type.GROUPCHAT : Entities.Message.Type.CHAT;
|
Entities.Message new_message = create_in_message(account, message);
|
||||||
Entities.Message new_message = new Entities.Message(message.body, type_);
|
|
||||||
|
determine_message_type(account, message, new_message);
|
||||||
|
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(new_message);
|
||||||
|
if (conversation != null) process_message(new_message, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entities.Message create_in_message(Account account, Xmpp.Message.Stanza message) {
|
||||||
|
Entities.Message new_message = new Entities.Message(message.body);
|
||||||
new_message.account = account;
|
new_message.account = account;
|
||||||
new_message.stanza_id = message.id;
|
new_message.stanza_id = message.id;
|
||||||
Jid from_jid = new Jid(message.from);
|
Jid from_jid = new Jid(message.from);
|
||||||
|
@ -105,18 +124,59 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
Xep.DelayedDelivery.MessageFlag? deleyed_delivery_flag = Xep.DelayedDelivery.MessageFlag.get_flag(message);
|
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_local();
|
new_message.time = deleyed_delivery_flag != null ? deleyed_delivery_flag.datetime : new DateTime.now_local();
|
||||||
new_message.local_time = new DateTime.now_local();
|
new_message.local_time = new DateTime.now_local();
|
||||||
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(new_message.counterpart, account, Conversation.Type.CHAT);
|
return new_message;
|
||||||
pre_message_received(new_message, message, conversation);
|
}
|
||||||
|
|
||||||
bool is_uuid = new_message.stanza_id != null && Regex.match_simple("""[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}""", new_message.stanza_id);
|
private void process_message(Entities.Message new_message, Xmpp.Message.Stanza stanza) {
|
||||||
if ((is_uuid && !db.contains_message_by_stanza_id(new_message.stanza_id, conversation.account)) ||
|
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(new_message);
|
||||||
(!is_uuid && !db.contains_message(new_message, conversation.account))) {
|
if (conversation != null) {
|
||||||
new_message.persist(db);
|
pre_message_received(new_message, stanza, conversation);
|
||||||
add_message(new_message, conversation);
|
|
||||||
if (new_message.direction == Entities.Message.DIRECTION_SENT) {
|
bool is_uuid = new_message.stanza_id != null && Regex.match_simple("""[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}""", new_message.stanza_id);
|
||||||
message_sent(new_message, conversation);
|
if ((is_uuid && !db.contains_message_by_stanza_id(new_message.stanza_id, conversation.account)) ||
|
||||||
|
(!is_uuid && !db.contains_message(new_message, conversation.account))) {
|
||||||
|
new_message.persist(db);
|
||||||
|
add_message(new_message, conversation);
|
||||||
|
if (new_message.direction == Entities.Message.DIRECTION_SENT) {
|
||||||
|
message_sent(new_message, conversation);
|
||||||
|
} else {
|
||||||
|
message_received(new_message, conversation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void determine_message_type(Account account, Xmpp.Message.Stanza message_stanza, Entities.Message message) {
|
||||||
|
if (message_stanza.type_ == Xmpp.Message.Stanza.TYPE_GROUPCHAT) {
|
||||||
|
message.type_ = Entities.Message.Type.GROUPCHAT;
|
||||||
|
process_message(message, message_stanza);
|
||||||
|
} else if (message_stanza.type_ == Xmpp.Message.Stanza.TYPE_CHAT) {
|
||||||
|
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(message.counterpart.bare_jid, account);
|
||||||
|
if (conversation != null) {
|
||||||
|
if (conversation.type_ == Conversation.Type.CHAT) {
|
||||||
|
message.type_ = Entities.Message.Type.CHAT;
|
||||||
|
} else if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||||
|
message.type_ = Entities.Message.Type.GROUPCHAT_PM;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message_received(new_message, conversation);
|
Core.XmppStream stream = stream_interactor.get_stream(account);
|
||||||
|
if (stream != null) stream.get_module(Xep.ServiceDiscovery.Module.IDENTITY).get_entity_categories(stream, message.counterpart.bare_jid.to_string(), (stream, identities, store) => {
|
||||||
|
Triple<MessageManager, Entities.Message, Xmpp.Message.Stanza> triple = store as Triple<MessageManager, Entities.Message, Xmpp.Message.Stanza>;
|
||||||
|
Entities.Message m = triple.b;
|
||||||
|
if (identities == null) {
|
||||||
|
m.type_ = Entities.Message.Type.CHAT;
|
||||||
|
triple.a.process_message(m, triple.c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (Xep.ServiceDiscovery.Identity identity in identities) {
|
||||||
|
if (identity.category == Xep.ServiceDiscovery.Identity.CATEGORY_CONFERENCE) {
|
||||||
|
m.type_ = Entities.Message.Type.GROUPCHAT_PM;
|
||||||
|
} else {
|
||||||
|
m.type_ = Entities.Message.Type.CHAT;
|
||||||
|
}
|
||||||
|
triple.a.process_message(m, triple.c);
|
||||||
|
}
|
||||||
|
}, Triple.create(this, message, message_stanza));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +189,8 @@ public class MessageManager : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entities.Message create_out_message(string text, Conversation conversation) {
|
private Entities.Message create_out_message(string text, Conversation conversation) {
|
||||||
Entities.Message.Type type_ = conversation.type_ == Conversation.Type.GROUPCHAT ? Entities.Message.Type.GROUPCHAT : Entities.Message.Type.CHAT;
|
Entities.Message message = new Entities.Message(text);
|
||||||
Entities.Message message = new Entities.Message(text, type_);
|
message.type_ = get_message_type_for_conversation(conversation);
|
||||||
message.stanza_id = random_uuid();
|
message.stanza_id = random_uuid();
|
||||||
message.account = conversation.account;
|
message.account = conversation.account;
|
||||||
message.body = text;
|
message.body = text;
|
||||||
|
|
|
@ -74,6 +74,7 @@ SOURCES
|
||||||
src/ui/conversation_list_titlebar.vala
|
src/ui/conversation_list_titlebar.vala
|
||||||
src/ui/conversation_selector/chat_row.vala
|
src/ui/conversation_selector/chat_row.vala
|
||||||
src/ui/conversation_selector/conversation_row.vala
|
src/ui/conversation_selector/conversation_row.vala
|
||||||
|
src/ui/conversation_selector/groupchat_pm_row.vala
|
||||||
src/ui/conversation_selector/groupchat_row.vala
|
src/ui/conversation_selector/groupchat_row.vala
|
||||||
src/ui/conversation_selector/list.vala
|
src/ui/conversation_selector/list.vala
|
||||||
src/ui/conversation_selector/view.vala
|
src/ui/conversation_selector/view.vala
|
||||||
|
|
|
@ -57,27 +57,7 @@ public class ChatRow : ConversationRow {
|
||||||
ArrayList<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
ArrayList<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
||||||
if (full_jids != null) {
|
if (full_jids != null) {
|
||||||
for (int i = 0; i < full_jids.size; i++) {
|
for (int i = 0; i < full_jids.size; i++) {
|
||||||
Box box = new Box(Orientation.HORIZONTAL, 5);
|
inner_box.add(get_fulljid_box(full_jids[i]));
|
||||||
|
|
||||||
Show show = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jids[i], conversation.account);
|
|
||||||
Image image = new Image();
|
|
||||||
if (show.as == Show.AWAY) {
|
|
||||||
image.set_from_icon_name("dino-status-away", IconSize.SMALL_TOOLBAR);
|
|
||||||
} else if (show.as == Show.XA || show.as == Show.DND) {
|
|
||||||
image.set_from_icon_name("dino-status-dnd", IconSize.SMALL_TOOLBAR);
|
|
||||||
} else if (show.as == Show.CHAT) {
|
|
||||||
image.set_from_icon_name("dino-status-chat", IconSize.SMALL_TOOLBAR);
|
|
||||||
} else {
|
|
||||||
image.set_from_icon_name("dino-status-online", IconSize.SMALL_TOOLBAR);
|
|
||||||
}
|
|
||||||
box.add(image);
|
|
||||||
|
|
||||||
Label resource = new Label(full_jids[i].resourcepart);
|
|
||||||
resource.xalign = 0;
|
|
||||||
box.add(resource);
|
|
||||||
box.show_all();
|
|
||||||
|
|
||||||
inner_box.add(box);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return main_box;
|
return main_box;
|
||||||
|
|
|
@ -120,6 +120,29 @@ public abstract class ConversationRow : ListBoxRow {
|
||||||
message_label.label = message_label.label;
|
message_label.label = message_label.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Box get_fulljid_box(Jid full_jid) {
|
||||||
|
Box box = new Box(Orientation.HORIZONTAL, 5) { visible=true };
|
||||||
|
|
||||||
|
Show show = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jid, conversation.account);
|
||||||
|
Image image = new Image() { visible=true };
|
||||||
|
if (show.as == Show.AWAY) {
|
||||||
|
image.set_from_icon_name("dino-status-away", IconSize.SMALL_TOOLBAR);
|
||||||
|
} else if (show.as == Show.XA || show.as == Show.DND) {
|
||||||
|
image.set_from_icon_name("dino-status-dnd", IconSize.SMALL_TOOLBAR);
|
||||||
|
} else if (show.as == Show.CHAT) {
|
||||||
|
image.set_from_icon_name("dino-status-chat", IconSize.SMALL_TOOLBAR);
|
||||||
|
} else {
|
||||||
|
image.set_from_icon_name("dino-status-online", IconSize.SMALL_TOOLBAR);
|
||||||
|
}
|
||||||
|
box.add(image);
|
||||||
|
|
||||||
|
Label resource = new Label(full_jid.resourcepart) { visible=true };
|
||||||
|
resource.xalign = 0;
|
||||||
|
box.add(resource);
|
||||||
|
box.show_all();
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
private void on_x_button_clicked() {
|
private void on_x_button_clicked() {
|
||||||
main_revealer.set_transition_type(RevealerTransitionType.SLIDE_UP);
|
main_revealer.set_transition_type(RevealerTransitionType.SLIDE_UP);
|
||||||
main_revealer.set_reveal_child(false);
|
main_revealer.set_reveal_child(false);
|
||||||
|
|
54
main/src/ui/conversation_selector/groupchat_pm_row.vala
Normal file
54
main/src/ui/conversation_selector/groupchat_pm_row.vala
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Gdk;
|
||||||
|
using Gee;
|
||||||
|
using Gtk;
|
||||||
|
|
||||||
|
using Xmpp;
|
||||||
|
using Dino.Entities;
|
||||||
|
|
||||||
|
namespace Dino.Ui.ConversationSelector {
|
||||||
|
|
||||||
|
public class GroupchatPmRow : ConversationRow {
|
||||||
|
|
||||||
|
public GroupchatPmRow(StreamInteractor stream_interactor, Conversation conversation) {
|
||||||
|
base(stream_interactor, conversation);
|
||||||
|
has_tooltip = true;
|
||||||
|
query_tooltip.connect ((x, y, keyboard_tooltip, tooltip) => {
|
||||||
|
tooltip.set_custom(generate_tooltip());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
update_avatar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void on_show_received(Show show) {
|
||||||
|
update_avatar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void network_connection(bool connected) {
|
||||||
|
if (!connected) {
|
||||||
|
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor)).set_greyscale(true).draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||||
|
} else {
|
||||||
|
update_avatar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update_avatar() {
|
||||||
|
ArrayList<Jid> full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
||||||
|
set_avatar((new AvatarGenerator(AVATAR_SIZE, AVATAR_SIZE, image.scale_factor))
|
||||||
|
.set_greyscale(full_jids == null)
|
||||||
|
.draw_conversation(stream_interactor, conversation), image.scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Widget generate_tooltip() {
|
||||||
|
Builder builder = new Builder.from_resource("/org/dino-im/conversation_selector/chat_row_tooltip.ui");
|
||||||
|
Box main_box = builder.get_object("main_box") as Box;
|
||||||
|
Box inner_box = builder.get_object("inner_box") as Box;
|
||||||
|
Label jid_label = builder.get_object("jid_label") as Label;
|
||||||
|
jid_label.label = conversation.counterpart.to_string();
|
||||||
|
if (stream_interactor.get_module(MucManager.IDENTITY).get_nick(conversation.counterpart, conversation.account) != null) {
|
||||||
|
inner_box.add(get_fulljid_box(conversation.counterpart));
|
||||||
|
}
|
||||||
|
return main_box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -39,8 +39,9 @@ public class List : ListBox {
|
||||||
});
|
});
|
||||||
stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect((show, jid, account) => {
|
stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect((show, jid, account) => {
|
||||||
Idle.add(() => {
|
Idle.add(() => {
|
||||||
Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
|
foreach (Conversation conversation in stream_interactor.get_module(ConversationManager.IDENTITY).get_conversations_for_presence(show, account)) {
|
||||||
if (conversation != null && rows.has_key(conversation)) rows[conversation].on_show_received(show);
|
if (rows.has_key(conversation)) rows[conversation].on_show_received(show);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -123,6 +124,8 @@ public class List : ListBox {
|
||||||
if (!rows.has_key(conversation)) {
|
if (!rows.has_key(conversation)) {
|
||||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||||
row = new GroupchatRow(stream_interactor, conversation);
|
row = new GroupchatRow(stream_interactor, conversation);
|
||||||
|
} else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM){
|
||||||
|
row = new GroupchatPmRow(stream_interactor, conversation);
|
||||||
} else {
|
} else {
|
||||||
row = new ChatRow(stream_interactor, conversation);
|
row = new ChatRow(stream_interactor, conversation);
|
||||||
}
|
}
|
||||||
|
@ -186,6 +189,8 @@ public class List : ListBox {
|
||||||
if (cr1 != null && cr2 != null) {
|
if (cr1 != null && cr2 != null) {
|
||||||
Conversation c1 = cr1.conversation;
|
Conversation c1 = cr1.conversation;
|
||||||
Conversation c2 = cr2.conversation;
|
Conversation c2 = cr2.conversation;
|
||||||
|
if (c1.last_active == null) return -1;
|
||||||
|
if (c2.last_active == null) return 1;
|
||||||
int comp = c2.last_active.compare(c1.last_active);
|
int comp = c2.last_active.compare(c1.last_active);
|
||||||
if (comp == 0) {
|
if (comp == 0) {
|
||||||
return Util.get_conversation_display_name(stream_interactor, c1)
|
return Util.get_conversation_display_name(stream_interactor, c1)
|
||||||
|
|
|
@ -151,6 +151,8 @@ public class View : Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load_earlier_messages() {
|
private void load_earlier_messages() {
|
||||||
|
if (earliest_message == null) return;
|
||||||
|
|
||||||
was_value = scrolled.vadjustment.value;
|
was_value = scrolled.vadjustment.value;
|
||||||
lock(reloading_lock) {
|
lock(reloading_lock) {
|
||||||
if(reloading) return;
|
if(reloading) return;
|
||||||
|
|
|
@ -40,6 +40,9 @@ public class Util : Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string get_conversation_display_name(StreamInteractor stream_interactor, Conversation conversation) {
|
public static string get_conversation_display_name(StreamInteractor stream_interactor, Conversation conversation) {
|
||||||
|
if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
|
||||||
|
return conversation.counterpart.resourcepart + " from " + get_display_name(stream_interactor, conversation.counterpart.bare_jid, conversation.account);
|
||||||
|
}
|
||||||
return get_display_name(stream_interactor, conversation.counterpart, conversation.account);
|
return get_display_name(stream_interactor, conversation.counterpart, conversation.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,9 @@ SOURCES
|
||||||
"src/module/util.vala"
|
"src/module/util.vala"
|
||||||
|
|
||||||
"src/module/xep/0030_service_discovery/flag.vala"
|
"src/module/xep/0030_service_discovery/flag.vala"
|
||||||
|
"src/module/xep/0030_service_discovery/identity.vala"
|
||||||
"src/module/xep/0030_service_discovery/info_result.vala"
|
"src/module/xep/0030_service_discovery/info_result.vala"
|
||||||
|
"src/module/xep/0030_service_discovery/item.vala"
|
||||||
"src/module/xep/0030_service_discovery/items_result.vala"
|
"src/module/xep/0030_service_discovery/items_result.vala"
|
||||||
"src/module/xep/0030_service_discovery/module.vala"
|
"src/module/xep/0030_service_discovery/module.vala"
|
||||||
"src/module/xep/0045_muc/flag.vala"
|
"src/module/xep/0045_muc/flag.vala"
|
||||||
|
|
|
@ -7,15 +7,34 @@ namespace Xmpp.Xep.ServiceDiscovery {
|
||||||
public class Flag : XmppStreamFlag {
|
public class Flag : XmppStreamFlag {
|
||||||
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "service_discovery");
|
public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "service_discovery");
|
||||||
|
|
||||||
private HashMap<string, ArrayList<string>> entity_features = new HashMap<string, ArrayList<string>>();
|
private HashMap<string, ArrayList<string>?> entity_features = new HashMap<string, ArrayList<string>?>();
|
||||||
|
private HashMap<string, ArrayList<Identity>?> entity_identities = new HashMap<string, ArrayList<Identity>?>();
|
||||||
public ArrayList<string> features = new ArrayList<string>();
|
public ArrayList<string> features = new ArrayList<string>();
|
||||||
|
|
||||||
|
public ArrayList<Identity>? get_entity_categories(string jid) {
|
||||||
|
return entity_identities.has_key(jid) ? entity_identities[jid] : null; // TODO isnt this default for hashmap
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool? has_entity_identity(string jid, string category, string type) {
|
||||||
|
if (!entity_identities.has_key(jid)) return null;
|
||||||
|
if (entity_identities[jid] == null) return false;
|
||||||
|
foreach (Identity identity in entity_identities[jid]) {
|
||||||
|
if (identity.category == category && identity.type_ == type) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool? has_entity_feature(string jid, string feature) {
|
public bool? has_entity_feature(string jid, string feature) {
|
||||||
if (!entity_features.has_key(jid)) return null;
|
if (!entity_features.has_key(jid)) return null;
|
||||||
|
if (entity_features[jid] == null) return false;
|
||||||
return entity_features[jid].contains(feature);
|
return entity_features[jid].contains(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_entitiy_features(string jid, ArrayList<string> features) {
|
public void set_entity_identities(string jid, ArrayList<Identity>? identities) {
|
||||||
|
entity_identities[jid] = identities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_entity_features(string jid, ArrayList<string>? features) {
|
||||||
entity_features[jid] = features;
|
entity_features[jid] = features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Xmpp.Xep.ServiceDiscovery {
|
||||||
|
|
||||||
|
public class Identity {
|
||||||
|
public const string CATEGORY_CLIENT = "client";
|
||||||
|
public const string CATEGORY_CONFERENCE = "conference";
|
||||||
|
|
||||||
|
public string category { get; set; }
|
||||||
|
public string type_ { get; set; }
|
||||||
|
public string? name { get; set; }
|
||||||
|
|
||||||
|
public Identity(string category, string type, string? name = null) {
|
||||||
|
this.category = category;
|
||||||
|
this.type_ = type;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -39,6 +39,27 @@ public class InfoResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InfoResult(Iq.Stanza iq_request) {
|
||||||
|
iq = new Iq.Stanza.result(iq_request);
|
||||||
|
iq.to = iq_request.from;
|
||||||
|
iq.stanza.put_node(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
|
||||||
|
}
|
||||||
|
|
||||||
|
private InfoResult.from_iq(Iq.Stanza iq) {
|
||||||
|
this.iq = iq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InfoResult? create_from_iq(Iq.Stanza iq) {
|
||||||
|
if (iq.is_error()) return null;
|
||||||
|
StanzaNode query_node = iq.stanza.get_subnode("query", NS_URI_INFO);
|
||||||
|
if (query_node == null) return null;
|
||||||
|
StanzaNode feature_node = query_node.get_subnode("feature", NS_URI_INFO);
|
||||||
|
if (feature_node == null) return null;
|
||||||
|
StanzaNode identity_node = query_node.get_subnode("identity", NS_URI_INFO);
|
||||||
|
if (identity_node == null) return null;
|
||||||
|
return new ServiceDiscovery.InfoResult.from_iq(iq);
|
||||||
|
}
|
||||||
|
|
||||||
public void add_feature(string feature) {
|
public void add_feature(string feature) {
|
||||||
iq.stanza.get_subnode("query", NS_URI_INFO).put_node(new StanzaNode.build("feature", NS_URI_INFO).put_attribute("var", feature));
|
iq.stanza.get_subnode("query", NS_URI_INFO).put_node(new StanzaNode.build("feature", NS_URI_INFO).put_attribute("var", feature));
|
||||||
}
|
}
|
||||||
|
@ -52,27 +73,6 @@ public class InfoResult {
|
||||||
}
|
}
|
||||||
iq.stanza.get_subnode("query", NS_URI_INFO).put_node(identity_node);
|
iq.stanza.get_subnode("query", NS_URI_INFO).put_node(identity_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InfoResult.from_iq(Iq.Stanza iq) {
|
|
||||||
this.iq = iq;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InfoResult(Iq.Stanza iq_request) {
|
|
||||||
iq = new Iq.Stanza.result(iq_request);
|
|
||||||
iq.to = iq_request.from;
|
|
||||||
iq.stanza.put_node(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InfoResult? create_from_iq(Iq.Stanza iq) {
|
|
||||||
if (iq.is_error()) return null;
|
|
||||||
StanzaNode query_node = iq.stanza.get_subnode("query", NS_URI_INFO);
|
|
||||||
if (query_node == null) return null;
|
|
||||||
StanzaNode feature_node = query_node.get_subnode("feature", NS_URI_INFO);
|
|
||||||
if (feature_node == null) return null;
|
|
||||||
StanzaNode identity_node = query_node.get_subnode("identity", NS_URI_INFO);
|
|
||||||
if (identity_node == null) return null;
|
|
||||||
return new ServiceDiscovery.InfoResult.from_iq(iq);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
15
xmpp-vala/src/module/xep/0030_service_discovery/item.vala
Normal file
15
xmpp-vala/src/module/xep/0030_service_discovery/item.vala
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
namespace Xmpp.Xep.ServiceDiscovery {
|
||||||
|
|
||||||
|
public class Item {
|
||||||
|
public string jid;
|
||||||
|
public string? name;
|
||||||
|
public string? node;
|
||||||
|
|
||||||
|
public Item(string jid, string? name = null, string? node = null) {
|
||||||
|
this.jid = jid;
|
||||||
|
this.name = name;
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,109 +3,94 @@ using Gee;
|
||||||
using Xmpp.Core;
|
using Xmpp.Core;
|
||||||
|
|
||||||
namespace Xmpp.Xep.ServiceDiscovery {
|
namespace Xmpp.Xep.ServiceDiscovery {
|
||||||
private const string NS_URI = "http://jabber.org/protocol/disco";
|
|
||||||
public const string NS_URI_INFO = NS_URI + "#info";
|
|
||||||
public const string NS_URI_ITEMS = NS_URI + "#items";
|
|
||||||
|
|
||||||
public class Module : XmppStreamModule, Iq.Handler {
|
private const string NS_URI = "http://jabber.org/protocol/disco";
|
||||||
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0030_service_discovery_module");
|
public const string NS_URI_INFO = NS_URI + "#info";
|
||||||
|
public const string NS_URI_ITEMS = NS_URI + "#items";
|
||||||
|
|
||||||
public ArrayList<Identity> identities = new ArrayList<Identity>();
|
public class Module : XmppStreamModule, Iq.Handler {
|
||||||
|
public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0030_service_discovery_module");
|
||||||
|
|
||||||
public Module.with_identity(string category, string type, string? name = null) {
|
public ArrayList<Identity> identities = new ArrayList<Identity>();
|
||||||
add_identity(category, type, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add_feature(XmppStream stream, string feature) {
|
public Module.with_identity(string category, string type, string? name = null) {
|
||||||
stream.get_flag(Flag.IDENTITY).add_own_feature(feature);
|
add_identity(category, type, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_feature_notify(XmppStream stream, string feature) {
|
public void add_feature(XmppStream stream, string feature) {
|
||||||
add_feature(stream, feature + "+notify");
|
stream.get_flag(Flag.IDENTITY).add_own_feature(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add_identity(string category, string type, string? name = null) {
|
public void add_feature_notify(XmppStream stream, string feature) {
|
||||||
identities.add(new Identity(category, type, name));
|
add_feature(stream, feature + "+notify");
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (has_target = false)] public delegate void OnInfoResult(XmppStream stream, InfoResult query_result, Object? store);
|
public void add_identity(string category, string type, string? name = null) {
|
||||||
public void request_info(XmppStream stream, string jid, OnInfoResult listener, Object? store) {
|
identities.add(new Identity(category, type, name));
|
||||||
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
|
}
|
||||||
iq.to = jid;
|
|
||||||
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, on_request_info_response, Tuple.create(listener, store));
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (has_target = false)] public delegate void OnItemsResult(XmppStream stream, ItemsResult query_result);
|
[CCode (has_target = false)] public delegate void HasEntryCategoryRes(XmppStream stream, ArrayList<Identity>? identities, Object? store);
|
||||||
public void request_items(XmppStream stream, string jid, OnItemsResult listener, Object? store) {
|
public void get_entity_categories(XmppStream stream, string jid, HasEntryCategoryRes on_result, Object? store) {
|
||||||
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns());
|
ArrayList<Identity>? res = stream.get_flag(Flag.IDENTITY).get_entity_categories(jid);
|
||||||
iq.to = jid;
|
if (res != null) on_result(stream, res, store);
|
||||||
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
|
request_info(stream, jid, (stream, query_result, store) => {
|
||||||
}
|
Tuple<HasEntryCategoryRes, Object> tuple = store as Tuple<HasEntryCategoryRes, Object>;
|
||||||
|
tuple.a(stream, query_result != null ? query_result.identities : null, tuple.b);
|
||||||
|
}, Tuple.create(on_result, store));
|
||||||
|
}
|
||||||
|
|
||||||
public void on_iq_get(XmppStream stream, Iq.Stanza iq) {
|
[CCode (has_target = false)] public delegate void OnInfoResult(XmppStream stream, InfoResult? query_result, Object? store);
|
||||||
StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI_INFO);
|
public void request_info(XmppStream stream, string jid, OnInfoResult listener, Object? store) {
|
||||||
if (query_node != null) {
|
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns());
|
||||||
send_query_result(stream, iq);
|
iq.to = jid;
|
||||||
}
|
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq, o) => {
|
||||||
}
|
|
||||||
|
|
||||||
public void on_iq_set(XmppStream stream, Iq.Stanza iq) { }
|
|
||||||
|
|
||||||
public override void attach(XmppStream stream) {
|
|
||||||
Iq.Module.require(stream);
|
|
||||||
stream.get_module(Iq.Module.IDENTITY).register_for_namespace(NS_URI_INFO, this);
|
|
||||||
stream.add_flag(new Flag());
|
|
||||||
add_feature(stream, NS_URI_INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void detach(XmppStream stream) { }
|
|
||||||
|
|
||||||
public static void require(XmppStream stream) {
|
|
||||||
if (stream.get_module(IDENTITY) == null) stream.add_module(new ServiceDiscovery.Module());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string get_ns() { return NS_URI; }
|
|
||||||
public override string get_id() { return IDENTITY.id; }
|
|
||||||
|
|
||||||
private static void on_request_info_response(XmppStream stream, Iq.Stanza iq, Object o) {
|
|
||||||
Tuple<OnInfoResult, Object> tuple = o as Tuple<OnInfoResult, Object>;
|
Tuple<OnInfoResult, Object> tuple = o as Tuple<OnInfoResult, Object>;
|
||||||
OnInfoResult on_result = tuple.a;
|
OnInfoResult on_result = tuple.a;
|
||||||
InfoResult? result = InfoResult.create_from_iq(iq);
|
InfoResult? result = InfoResult.create_from_iq(iq);
|
||||||
if (result != null) {
|
stream.get_flag(Flag.IDENTITY).set_entity_features(iq.from, result != null ? result.features : null);
|
||||||
stream.get_flag(Flag.IDENTITY).set_entitiy_features(iq.from, result.features);
|
stream.get_flag(Flag.IDENTITY).set_entity_identities(iq.from, result != null ? result.identities : null);
|
||||||
on_result(stream, result, tuple.b);
|
on_result(stream, result, tuple.b);
|
||||||
}
|
}, Tuple.create(listener, store));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void send_query_result(XmppStream stream, Iq.Stanza iq_request) {
|
[CCode (has_target = false)] public delegate void OnItemsResult(XmppStream stream, ItemsResult query_result);
|
||||||
InfoResult query_result = new ServiceDiscovery.InfoResult(iq_request);
|
public void request_items(XmppStream stream, string jid, OnItemsResult listener, Object? store) {
|
||||||
query_result.features = stream.get_flag(Flag.IDENTITY).features;
|
Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns());
|
||||||
query_result.identities = identities;
|
iq.to = jid;
|
||||||
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, query_result.iq);
|
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void on_iq_get(XmppStream stream, Iq.Stanza iq) {
|
||||||
|
StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI_INFO);
|
||||||
|
if (query_node != null) {
|
||||||
|
send_query_result(stream, iq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Identity {
|
public void on_iq_set(XmppStream stream, Iq.Stanza iq) { }
|
||||||
public string category { get; set; }
|
|
||||||
public string type_ { get; set; }
|
|
||||||
public string? name { get; set; }
|
|
||||||
|
|
||||||
public Identity(string category, string type, string? name = null) {
|
public override void attach(XmppStream stream) {
|
||||||
this.category = category;
|
Iq.Module.require(stream);
|
||||||
this.type_ = type;
|
stream.get_module(Iq.Module.IDENTITY).register_for_namespace(NS_URI_INFO, this);
|
||||||
this.name = name;
|
stream.add_flag(new Flag());
|
||||||
}
|
add_feature(stream, NS_URI_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Item {
|
public override void detach(XmppStream stream) { }
|
||||||
public string jid;
|
|
||||||
public string? name;
|
|
||||||
public string? node;
|
|
||||||
|
|
||||||
public Item(string jid, string? name = null, string? node = null) {
|
public static void require(XmppStream stream) {
|
||||||
this.jid = jid;
|
if (stream.get_module(IDENTITY) == null) stream.add_module(new ServiceDiscovery.Module());
|
||||||
this.name = name;
|
}
|
||||||
this.node = node;
|
|
||||||
}
|
public override string get_ns() { return NS_URI; }
|
||||||
|
public override string get_id() { return IDENTITY.id; }
|
||||||
|
|
||||||
|
private void send_query_result(XmppStream stream, Iq.Stanza iq_request) {
|
||||||
|
InfoResult query_result = new ServiceDiscovery.InfoResult(iq_request);
|
||||||
|
query_result.features = stream.get_flag(Flag.IDENTITY).features;
|
||||||
|
query_result.identities = identities;
|
||||||
|
stream.get_module(Iq.Module.IDENTITY).send_iq(stream, query_result.iq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ public class Module : XmppStreamModule {
|
||||||
string bare_jid = get_bare_jid(presence.from);
|
string bare_jid = get_bare_jid(presence.from);
|
||||||
ErrorStanza? error_stanza = presence.get_error();
|
ErrorStanza? error_stanza = presence.get_error();
|
||||||
if (flag.get_enter_id(bare_jid) == error_stanza.original_id) {
|
if (flag.get_enter_id(bare_jid) == error_stanza.original_id) {
|
||||||
ListenerHolder listener = flag.get_enter_listener(bare_jid);
|
ListenerHolder? listener = flag.get_enter_listener(bare_jid);
|
||||||
MucEnterError? error = null;
|
MucEnterError? error = null;
|
||||||
if (error_stanza.condition == ErrorStanza.CONDITION_NOT_AUTHORIZED && ErrorStanza.TYPE_AUTH == error_stanza.type_) {
|
if (error_stanza.condition == ErrorStanza.CONDITION_NOT_AUTHORIZED && ErrorStanza.TYPE_AUTH == error_stanza.type_) {
|
||||||
error = MucEnterError.PASSWORD_REQUIRED;
|
error = MucEnterError.PASSWORD_REQUIRED;
|
||||||
|
@ -144,7 +144,7 @@ public class Module : XmppStreamModule {
|
||||||
} else if (ErrorStanza.CONDITION_ITEM_NOT_FOUND == error_stanza.condition && ErrorStanza.TYPE_CANCEL == error_stanza.type_) {
|
} else if (ErrorStanza.CONDITION_ITEM_NOT_FOUND == error_stanza.condition && ErrorStanza.TYPE_CANCEL == error_stanza.type_) {
|
||||||
error = MucEnterError.ROOM_DOESNT_EXIST;
|
error = MucEnterError.ROOM_DOESNT_EXIST;
|
||||||
}
|
}
|
||||||
if (error == null) listener.on_error(stream, error, listener.reference);
|
if (error != null && listener != null) listener.on_error(stream, error, listener.reference);
|
||||||
flag.finish_muc_enter(bare_jid);
|
flag.finish_muc_enter(bare_jid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,12 +59,13 @@ namespace Xmpp.Xep.EntityCapabilities {
|
||||||
if (capabilities.size == 0) {
|
if (capabilities.size == 0) {
|
||||||
stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, presence.from, on_received_info_response, Tuple.create(storage, ver_attribute));
|
stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, presence.from, on_received_info_response, Tuple.create(storage, ver_attribute));
|
||||||
} else {
|
} else {
|
||||||
stream.get_flag(ServiceDiscovery.Flag.IDENTITY).set_entitiy_features(presence.from, capabilities);
|
stream.get_flag(ServiceDiscovery.Flag.IDENTITY).set_entity_features(presence.from, capabilities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void on_received_info_response(XmppStream stream, ServiceDiscovery.InfoResult query_result, Object? store) {
|
private static void on_received_info_response(XmppStream stream, ServiceDiscovery.InfoResult? query_result, Object? store) {
|
||||||
|
if (query_result == null) return;
|
||||||
Tuple<Storage, string> tuple = store as Tuple<Storage, string>;
|
Tuple<Storage, string> tuple = store as Tuple<Storage, string>;
|
||||||
Storage storage = tuple.a;
|
Storage storage = tuple.a;
|
||||||
string entity = tuple.b;
|
string entity = tuple.b;
|
||||||
|
|
Loading…
Reference in a new issue