parse more presence metadata
This commit is contained in:
parent
2e5e2ff6fe
commit
8be8d7df8f
|
@ -10,6 +10,7 @@ import im.conversations.android.database.entity.PresenceEntity;
|
|||
import im.conversations.android.database.model.Account;
|
||||
import im.conversations.android.database.model.PresenceShow;
|
||||
import im.conversations.android.database.model.PresenceType;
|
||||
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
||||
import java.util.Arrays;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.parts.Resourcepart;
|
||||
|
@ -37,7 +38,10 @@ public abstract class PresenceDao {
|
|||
@NonNull final Resourcepart resource,
|
||||
@Nullable final PresenceType type,
|
||||
@Nullable final PresenceShow show,
|
||||
@Nullable final String status) {
|
||||
@Nullable final String status,
|
||||
@Nullable final String vCardPhoto,
|
||||
@Nullable final String occupantId,
|
||||
@Nullable final MultiUserChat multiUserChat) {
|
||||
if (resource.equals(Resourcepart.EMPTY)
|
||||
&& Arrays.asList(PresenceType.ERROR, PresenceType.UNAVAILABLE).contains(type)) {
|
||||
deletePresences(account.id, address);
|
||||
|
@ -49,7 +53,17 @@ public abstract class PresenceDao {
|
|||
// unavailable presence only delete previous nothing left to do
|
||||
return;
|
||||
}
|
||||
final var entity = PresenceEntity.of(account.id, address, resource, type, show, status);
|
||||
final var entity =
|
||||
PresenceEntity.of(
|
||||
account.id,
|
||||
address,
|
||||
resource,
|
||||
type,
|
||||
show,
|
||||
status,
|
||||
vCardPhoto,
|
||||
occupantId,
|
||||
multiUserChat);
|
||||
insert(entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import im.conversations.android.database.model.PresenceShow;
|
|||
import im.conversations.android.database.model.PresenceType;
|
||||
import im.conversations.android.xmpp.model.muc.Affiliation;
|
||||
import im.conversations.android.xmpp.model.muc.Role;
|
||||
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.jxmpp.jid.parts.Resourcepart;
|
||||
|
@ -70,9 +71,13 @@ public class PresenceEntity {
|
|||
long account,
|
||||
@NonNull BareJid address,
|
||||
@NonNull Resourcepart resource,
|
||||
PresenceType type,
|
||||
PresenceShow show,
|
||||
String status) {
|
||||
final PresenceType type,
|
||||
final PresenceShow show,
|
||||
final String status,
|
||||
final String vCardPhoto,
|
||||
final String occupantId,
|
||||
final MultiUserChat multiUserChat) {
|
||||
final var mucItem = multiUserChat == null ? null : multiUserChat.getItem();
|
||||
final var entity = new PresenceEntity();
|
||||
entity.accountId = account;
|
||||
entity.address = address;
|
||||
|
@ -80,6 +85,14 @@ public class PresenceEntity {
|
|||
entity.type = type;
|
||||
entity.show = show;
|
||||
entity.status = status;
|
||||
entity.vCardPhoto = vCardPhoto;
|
||||
if (mucItem != null) {
|
||||
entity.occupantId = occupantId;
|
||||
entity.mucUserAffiliation = mucItem.getAffiliation();
|
||||
entity.mucUserRole = mucItem.getRole();
|
||||
entity.mucUserJid = mucItem.getJid();
|
||||
entity.mucUserSelf = multiUserChat.getStatus().contains(110);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ public class Resolver {
|
|||
}
|
||||
|
||||
private static List<ServiceRecord> resolveNoSrvRecords(DNSName dnsName, boolean includeCName) {
|
||||
List<ServiceRecord> results = new ArrayList<>();
|
||||
var results = new ImmutableList.Builder<ServiceRecord>();
|
||||
try {
|
||||
for (A a : resolveWithFallback(dnsName, A.class, false).getAnswersOrEmptySet()) {
|
||||
results.add(ServiceRecord.createDefault(dnsName, a.getInetAddress()));
|
||||
|
@ -238,17 +238,17 @@ public class Resolver {
|
|||
resolveWithFallback(dnsName, AAAA.class, false).getAnswersOrEmptySet()) {
|
||||
results.add(ServiceRecord.createDefault(dnsName, aaaa.getInetAddress()));
|
||||
}
|
||||
if (results.size() == 0 && includeCName) {
|
||||
if (results.build().isEmpty() && includeCName) {
|
||||
for (CNAME cname :
|
||||
resolveWithFallback(dnsName, CNAME.class, false).getAnswersOrEmptySet()) {
|
||||
results.addAll(resolveNoSrvRecords(cname.name, false));
|
||||
}
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
} catch (final Throwable throwable) {
|
||||
LOGGER.info("Error resolving fallback records", throwable);
|
||||
}
|
||||
results.add(ServiceRecord.createDefault(dnsName));
|
||||
return results;
|
||||
return results.build();
|
||||
}
|
||||
|
||||
private static ResolverResult<SRV> resolveWithFallback(
|
||||
|
|
|
@ -99,5 +99,7 @@ public final class Namespace {
|
|||
public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0";
|
||||
public static final String TLS = "urn:ietf:params:xml:ns:xmpp-tls";
|
||||
public static final String UNIFIED_PUSH = "http://gultsch.de/xmpp/drafts/unified-push";
|
||||
public static final String VCARD_TEMP = "vcard-temp";
|
||||
public static final String VCARD_TEMP_UPDATE = "vcard-temp:x:update";
|
||||
public static final String VERSION = "jabber:iq:version";
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import im.conversations.android.xmpp.manager.DiscoManager;
|
|||
import im.conversations.android.xmpp.manager.ExternalDiscoManager;
|
||||
import im.conversations.android.xmpp.manager.HttpUploadManager;
|
||||
import im.conversations.android.xmpp.manager.JingleConnectionManager;
|
||||
import im.conversations.android.xmpp.manager.MultiUserChatManager;
|
||||
import im.conversations.android.xmpp.manager.NickManager;
|
||||
import im.conversations.android.xmpp.manager.PepManager;
|
||||
import im.conversations.android.xmpp.manager.PresenceManager;
|
||||
|
@ -45,6 +46,7 @@ public final class Managers {
|
|||
.put(
|
||||
JingleConnectionManager.class,
|
||||
new JingleConnectionManager(context, connection))
|
||||
.put(MultiUserChatManager.class, new MultiUserChatManager(context, connection))
|
||||
.put(NickManager.class, new NickManager(context, connection))
|
||||
.put(PepManager.class, new PepManager(context, connection))
|
||||
.put(PresenceManager.class, new PresenceManager(context, connection))
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package im.conversations.android.xmpp.manager;
|
||||
|
||||
import android.content.Context;
|
||||
import im.conversations.android.xmpp.XmppConnection;
|
||||
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
||||
import im.conversations.android.xmpp.model.stanza.Presence;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.jid.parts.Resourcepart;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MultiUserChatManager extends AbstractManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MultiUserChatManager.class);
|
||||
|
||||
public MultiUserChatManager(Context context, XmppConnection connection) {
|
||||
super(context, connection);
|
||||
}
|
||||
|
||||
public void enter(final BareJid room) {
|
||||
final var presence = new Presence();
|
||||
presence.setTo(JidCreate.fullFrom(room, Resourcepart.fromOrThrowUnchecked("c3-test-user")));
|
||||
presence.addExtension(new MultiUserChat());
|
||||
LOGGER.info("sending {} ", presence);
|
||||
connection.sendPresencePacket(presence);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package im.conversations.android.xmpp.model.muc.user;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
import im.conversations.android.xmpp.model.muc.Affiliation;
|
||||
import im.conversations.android.xmpp.model.muc.Role;
|
||||
import java.util.Locale;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@XmlElement
|
||||
public class Item extends Extension {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Item.class);
|
||||
|
||||
public Item() {
|
||||
super(Item.class);
|
||||
}
|
||||
|
||||
public Affiliation getAffiliation() {
|
||||
final var affiliation = this.getAttribute("affiliation");
|
||||
if (Strings.isNullOrEmpty(affiliation)) {
|
||||
return Affiliation.NONE;
|
||||
}
|
||||
try {
|
||||
return Affiliation.valueOf(affiliation.toUpperCase(Locale.ROOT));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
LOGGER.warn("could not parse affiliation {}", affiliation);
|
||||
return Affiliation.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public Role getRole() {
|
||||
final var role = this.getAttribute("role");
|
||||
if (Strings.isNullOrEmpty(role)) {
|
||||
return Role.NONE;
|
||||
}
|
||||
try {
|
||||
return Role.valueOf(role.toUpperCase(Locale.ROOT));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
LOGGER.warn("could not parse role {}", role);
|
||||
return Role.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public String getNick() {
|
||||
return this.getAttribute("nick");
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
final var jid = this.getAttribute("jid");
|
||||
if (Strings.isNullOrEmpty(jid)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JidCreate.from(jid);
|
||||
} catch (final XmppStringprepException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
package im.conversations.android.xmpp.model.muc.user;
|
||||
|
||||
import com.google.common.collect.Collections2;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
@XmlElement(name = "x")
|
||||
public class MultiUserChat extends Extension {
|
||||
|
@ -9,4 +12,14 @@ public class MultiUserChat extends Extension {
|
|||
public MultiUserChat() {
|
||||
super(MultiUserChat.class);
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
return this.getExtension(Item.class);
|
||||
}
|
||||
|
||||
public Collection<Integer> getStatus() {
|
||||
return Collections2.filter(
|
||||
Collections2.transform(getExtensions(Status.class), Status::getCode),
|
||||
Objects::nonNull);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package im.conversations.android.xmpp.model.muc.user;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Status extends Extension {
|
||||
|
||||
public Status() {
|
||||
super(Status.class);
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return this.getOptionalIntAttribute("code").orNull();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package im.conversations.android.xmpp.model.vcard;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class VCard extends Extension {
|
||||
|
||||
public VCard() {
|
||||
super(VCard.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.VCARD_TEMP)
|
||||
package im.conversations.android.xmpp.model.vcard;
|
||||
|
||||
import im.conversations.android.annotation.XmlPackage;
|
||||
import im.conversations.android.xml.Namespace;
|
|
@ -0,0 +1,12 @@
|
|||
package im.conversations.android.xmpp.model.vcard.update;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Photo extends Extension {
|
||||
|
||||
public Photo() {
|
||||
super(Photo.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package im.conversations.android.xmpp.model.vcard.update;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement(name = "x")
|
||||
public class VCardUpdate extends Extension {
|
||||
|
||||
public VCardUpdate() {
|
||||
super(VCardUpdate.class);
|
||||
}
|
||||
|
||||
public Photo getPhoto() {
|
||||
return this.getExtension(Photo.class);
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
final var photo = getPhoto();
|
||||
return photo == null ? null : photo.getContent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.VCARD_TEMP_UPDATE)
|
||||
package im.conversations.android.xmpp.model.vcard.update;
|
||||
|
||||
import im.conversations.android.annotation.XmlPackage;
|
||||
import im.conversations.android.xml.Namespace;
|
|
@ -3,10 +3,14 @@ package im.conversations.android.xmpp.processor;
|
|||
import android.content.Context;
|
||||
import im.conversations.android.database.model.PresenceShow;
|
||||
import im.conversations.android.database.model.PresenceType;
|
||||
import im.conversations.android.xml.Namespace;
|
||||
import im.conversations.android.xmpp.Entity;
|
||||
import im.conversations.android.xmpp.XmppConnection;
|
||||
import im.conversations.android.xmpp.manager.DiscoManager;
|
||||
import im.conversations.android.xmpp.model.muc.user.MultiUserChat;
|
||||
import im.conversations.android.xmpp.model.occupant.OccupantId;
|
||||
import im.conversations.android.xmpp.model.stanza.Presence;
|
||||
import im.conversations.android.xmpp.model.vcard.update.VCardUpdate;
|
||||
import java.util.function.Consumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -38,9 +42,35 @@ public class PresenceProcessor extends XmppConnection.Delegate implements Consum
|
|||
}
|
||||
final var show = PresenceShow.of(presencePacket.findChildContent("show"));
|
||||
final var status = presencePacket.findChildContent("status");
|
||||
getDatabase().presenceDao().set(getAccount(), address, resource, type, show, status);
|
||||
|
||||
// TODO store presence info (vCard + muc#user stuff + occupantId)
|
||||
final var vCardUpdate = presencePacket.getExtension(VCardUpdate.class);
|
||||
final var vCardPhoto = vCardUpdate == null ? null : vCardUpdate.getHash();
|
||||
final var muc = presencePacket.getExtension(MultiUserChat.class);
|
||||
|
||||
final String occupantId;
|
||||
if (muc != null && presencePacket.hasExtension(OccupantId.class)) {
|
||||
if (getManager(DiscoManager.class)
|
||||
.hasFeature(Entity.discoItem(address), Namespace.OCCUPANT_ID)) {
|
||||
occupantId = presencePacket.getExtension(OccupantId.class).getId();
|
||||
} else {
|
||||
occupantId = null;
|
||||
}
|
||||
} else {
|
||||
occupantId = null;
|
||||
}
|
||||
|
||||
getDatabase()
|
||||
.presenceDao()
|
||||
.set(
|
||||
getAccount(),
|
||||
address,
|
||||
resource,
|
||||
type,
|
||||
show,
|
||||
status,
|
||||
vCardPhoto,
|
||||
occupantId,
|
||||
muc);
|
||||
|
||||
// TODO do this only for contacts?
|
||||
fetchCapabilities(presencePacket);
|
||||
|
|
Loading…
Reference in a new issue