fetch roster. process result
This commit is contained in:
parent
9e7bbcc272
commit
6b232f7a5a
|
@ -1,6 +1,7 @@
|
|||
package eu.siacs.conversations.xml;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
@ -177,14 +178,14 @@ public class Element {
|
|||
|
||||
public Jid getAttributeAsJid(String name) {
|
||||
final String jid = this.getAttribute(name);
|
||||
if (jid != null && !jid.isEmpty()) {
|
||||
try {
|
||||
return Jid.ofEscaped(jid);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return InvalidJid.of(jid, this instanceof MessagePacket);
|
||||
}
|
||||
if (Strings.isNullOrEmpty(jid)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Jid.ofEscaped(jid);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return InvalidJid.of(jid, this instanceof MessagePacket);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Hashtable<String, String> getAttributes() {
|
||||
|
@ -215,6 +216,7 @@ public class Element {
|
|||
return elementOutput.toString();
|
||||
}
|
||||
|
||||
// TODO should ultimately be removed once everything is an extension
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.room.TypeConverters;
|
|||
import im.conversations.android.database.dao.AccountDao;
|
||||
import im.conversations.android.database.dao.MessageDao;
|
||||
import im.conversations.android.database.dao.PresenceDao;
|
||||
import im.conversations.android.database.dao.RosterDao;
|
||||
import im.conversations.android.database.entity.AccountEntity;
|
||||
import im.conversations.android.database.entity.BlockedItemEntity;
|
||||
import im.conversations.android.database.entity.ChatEntity;
|
||||
|
@ -71,4 +72,6 @@ public abstract class ConversationsDatabase extends RoomDatabase {
|
|||
public abstract PresenceDao presenceDao();
|
||||
|
||||
public abstract MessageDao messageDao();
|
||||
|
||||
public abstract RosterDao rosterDao();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package im.conversations.android.database.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
import im.conversations.android.database.entity.RosterItemEntity;
|
||||
import im.conversations.android.database.model.Account;
|
||||
import java.util.Collection;
|
||||
|
||||
@Dao
|
||||
public abstract class RosterDao {
|
||||
|
||||
@Insert
|
||||
protected abstract void insert(Collection<RosterItemEntity> rosterItems);
|
||||
|
||||
@Query("DELETE FROM roster WHERE accountId=:account")
|
||||
protected abstract void clear(final long account);
|
||||
|
||||
@Query("UPDATE account SET rosterVersion=:version WHERE id=:account")
|
||||
protected abstract void setRosterVersion(final long account, final String version);
|
||||
|
||||
@Transaction
|
||||
public void setRoster(
|
||||
final Account account,
|
||||
final String version,
|
||||
final Collection<RosterItemEntity> rosterItems) {
|
||||
clear(account.id);
|
||||
insert(rosterItems);
|
||||
setRosterVersion(account.id, version);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,10 @@ import androidx.room.Entity;
|
|||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
import im.conversations.android.database.model.Subscription;
|
||||
import com.google.common.collect.Collections2;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import im.conversations.android.xmpp.model.roster.Item;
|
||||
import java.util.Collection;
|
||||
|
||||
@Entity(
|
||||
tableName = "roster",
|
||||
|
@ -27,11 +30,26 @@ public class RosterItemEntity {
|
|||
|
||||
@NonNull public Long accountId;
|
||||
|
||||
@NonNull public String address;
|
||||
@NonNull public Jid address;
|
||||
|
||||
public Subscription subscription;
|
||||
public Item.Subscription subscription;
|
||||
|
||||
public boolean ask;
|
||||
public boolean isPendingOut;
|
||||
|
||||
public String name;
|
||||
|
||||
public static RosterItemEntity of(final long accountId, final Item item) {
|
||||
final var entity = new RosterItemEntity();
|
||||
entity.accountId = accountId;
|
||||
entity.address = item.getJid();
|
||||
entity.subscription = item.getSubscription();
|
||||
entity.isPendingOut = item.isPendingOut();
|
||||
entity.name = item.getItemName();
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static Collection<RosterItemEntity> of(
|
||||
final long accountId, final Collection<Item> items) {
|
||||
return Collections2.transform(items, i -> of(accountId, i));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package im.conversations.android.database.model;
|
||||
|
||||
public enum Subscription {
|
||||
NONE,
|
||||
TO,
|
||||
FROM,
|
||||
BOTH
|
||||
}
|
|
@ -1,13 +1,49 @@
|
|||
package im.conversations.android.xmpp.model.roster;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@XmlElement
|
||||
public class Item extends Extension {
|
||||
|
||||
public static final List<Subscription> RESULT_SUBSCRIPTIONS =
|
||||
Arrays.asList(Subscription.NONE, Subscription.TO, Subscription.FROM, Subscription.BOTH);
|
||||
|
||||
public Item() {
|
||||
super("item", Namespace.ROSTER);
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
return getAttributeAsJid("jid");
|
||||
}
|
||||
|
||||
public String getItemName() {
|
||||
return this.getAttribute("name");
|
||||
}
|
||||
|
||||
public boolean isPendingOut() {
|
||||
return "subscribe".equalsIgnoreCase(this.getAttribute("ask"));
|
||||
}
|
||||
|
||||
public Subscription getSubscription() {
|
||||
final String value = this.getAttribute("subscription");
|
||||
try {
|
||||
return value == null ? null : Subscription.valueOf(value.toLowerCase(Locale.ROOT));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Subscription {
|
||||
NONE,
|
||||
TO,
|
||||
FROM,
|
||||
BOTH,
|
||||
REMOVE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,8 @@ public class Query extends Extension {
|
|||
public void setVersion(final String rosterVersion) {
|
||||
this.setAttribute("ver", rosterVersion);
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return this.getAttribute("ver");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package im.conversations.android.xmpp.processor;
|
|||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Collections2;
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import im.conversations.android.database.entity.RosterItemEntity;
|
||||
import im.conversations.android.xmpp.XmppConnection;
|
||||
import im.conversations.android.xmpp.model.roster.Item;
|
||||
import im.conversations.android.xmpp.model.roster.Query;
|
||||
|
@ -52,19 +54,29 @@ public class BindProcessor extends AbstractBaseProcessor implements Consumer<Jid
|
|||
Log.d(Config.LOGTAG, account.address + ": fetching roster version " + rosterVersion);
|
||||
rosterQuery.setVersion(rosterVersion);
|
||||
}
|
||||
connection.sendIqPacket(
|
||||
iqPacket,
|
||||
result -> {
|
||||
if (result.getType() != IqPacket.TYPE.RESULT) {
|
||||
return;
|
||||
}
|
||||
final Query query = result.getExtension(Query.class);
|
||||
if (query == null) {
|
||||
// No query in result means further modifications are sent via pushes
|
||||
return;
|
||||
}
|
||||
// TODO delete entire roster
|
||||
for (final Item item : query.getExtensions(Item.class)) {}
|
||||
});
|
||||
connection.sendIqPacket(iqPacket, this::handleFetchRosterResult);
|
||||
}
|
||||
|
||||
private void handleFetchRosterResult(final IqPacket result) {
|
||||
if (result.getType() != IqPacket.TYPE.RESULT) {
|
||||
return;
|
||||
}
|
||||
final Query query = result.getExtension(Query.class);
|
||||
if (query == null) {
|
||||
// No query in result means further modifications are sent via pushes
|
||||
return;
|
||||
}
|
||||
final var account = getAccount();
|
||||
final var database = getDatabase();
|
||||
final var version = query.getVersion();
|
||||
final var items = query.getExtensions(Item.class);
|
||||
// In a roster result (Section 2.1.4), the client MUST ignore values of the c'subscription'
|
||||
// attribute other than "none", "to", "from", or "both".
|
||||
final var validItems =
|
||||
Collections2.filter(
|
||||
items,
|
||||
i -> i != null && Item.RESULT_SUBSCRIPTIONS.contains(i.getSubscription()));
|
||||
final var entities = RosterItemEntity.of(account.id, validItems);
|
||||
database.rosterDao().setRoster(account, version, entities);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue