mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 16:57:50 +00:00
Added admins to groups.
Only process group updates if an admin sent it.
This commit is contained in:
parent
23a5fa7580
commit
b6d2717286
@ -72,6 +72,7 @@ import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -246,7 +247,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isSignalGroup()) {
|
if (isSignalGroup()) {
|
||||||
new CreateSignalGroupTask(this, avatarBmp, getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
Recipient local = Recipient.from(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)), false);
|
||||||
|
new CreateSignalGroupTask(this, avatarBmp, getGroupName(), getAdapter().getRecipients(), Collections.singleton(local)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
} else {
|
} else {
|
||||||
new CreateMmsGroupTask(this, getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
new CreateMmsGroupTask(this, getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
@ -254,7 +256,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
private void handleGroupUpdate() {
|
private void handleGroupUpdate() {
|
||||||
new UpdateSignalGroupTask(this, groupToUpdate.get().id, avatarBmp,
|
new UpdateSignalGroupTask(this, groupToUpdate.get().id, avatarBmp,
|
||||||
getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
getGroupName(), getAdapter().getRecipients(), groupToUpdate.get().admins).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleOpenConversation(long threadId, Recipient recipient) {
|
private void handleOpenConversation(long threadId, Recipient recipient) {
|
||||||
@ -344,9 +346,10 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
for (Recipient recipient : members) {
|
for (Recipient recipient : members) {
|
||||||
memberAddresses.add(recipient.getAddress());
|
memberAddresses.add(recipient.getAddress());
|
||||||
}
|
}
|
||||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(activity)));
|
Address local = Address.fromSerialized(TextSecurePreferences.getLocalNumber(activity));
|
||||||
|
memberAddresses.add(local);
|
||||||
|
|
||||||
String groupId = DatabaseFactory.getGroupDatabase(activity).getOrCreateGroupForMembers(memberAddresses, true);
|
String groupId = DatabaseFactory.getGroupDatabase(activity).getOrCreateGroupForMembers(memberAddresses, true, Collections.singletonList(local));
|
||||||
Recipient groupRecipient = Recipient.from(activity, Address.fromSerialized(groupId), true);
|
Recipient groupRecipient = Recipient.from(activity, Address.fromSerialized(groupId), true);
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(activity).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.DEFAULT);
|
long threadId = DatabaseFactory.getThreadDatabase(activity).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
|
|
||||||
@ -370,16 +373,19 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
protected Bitmap avatar;
|
protected Bitmap avatar;
|
||||||
protected Set<Recipient> members;
|
protected Set<Recipient> members;
|
||||||
protected String name;
|
protected String name;
|
||||||
|
protected Set<Recipient> admins;
|
||||||
|
|
||||||
public SignalGroupTask(GroupCreateActivity activity,
|
public SignalGroupTask(GroupCreateActivity activity,
|
||||||
Bitmap avatar,
|
Bitmap avatar,
|
||||||
String name,
|
String name,
|
||||||
Set<Recipient> members)
|
Set<Recipient> members,
|
||||||
|
Set<Recipient> admins)
|
||||||
{
|
{
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.avatar = avatar;
|
this.avatar = avatar;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.members = members;
|
this.members = members;
|
||||||
|
this.admins = admins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -403,13 +409,13 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class CreateSignalGroupTask extends SignalGroupTask {
|
private static class CreateSignalGroupTask extends SignalGroupTask {
|
||||||
public CreateSignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, Set<Recipient> members) {
|
public CreateSignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, Set<Recipient> members, Set<Recipient> admins) {
|
||||||
super(activity, avatar, name, members);
|
super(activity, avatar, name, members, admins);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<GroupActionResult> doInBackground(Void... aVoid) {
|
protected Optional<GroupActionResult> doInBackground(Void... aVoid) {
|
||||||
return Optional.of(GroupManager.createGroup(activity, members, avatar, name, false));
|
return Optional.of(GroupManager.createGroup(activity, members, avatar, name, false, admins));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -430,16 +436,16 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
private String groupId;
|
private String groupId;
|
||||||
|
|
||||||
public UpdateSignalGroupTask(GroupCreateActivity activity, String groupId,
|
public UpdateSignalGroupTask(GroupCreateActivity activity, String groupId,
|
||||||
Bitmap avatar, String name, Set<Recipient> members)
|
Bitmap avatar, String name, Set<Recipient> members, Set<Recipient> admins)
|
||||||
{
|
{
|
||||||
super(activity, avatar, name, members);
|
super(activity, avatar, name, members, admins);
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<GroupActionResult> doInBackground(Void... aVoid) {
|
protected Optional<GroupActionResult> doInBackground(Void... aVoid) {
|
||||||
try {
|
try {
|
||||||
return Optional.of(GroupManager.updateGroup(activity, groupId, members, avatar, name));
|
return Optional.of(GroupManager.updateGroup(activity, groupId, members, avatar, name, admins));
|
||||||
} catch (InvalidNumberException e) {
|
} catch (InvalidNumberException e) {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
@ -537,11 +543,17 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
existingContacts.addAll(recipients);
|
existingContacts.addAll(recipients);
|
||||||
|
|
||||||
if (group.isPresent()) {
|
if (group.isPresent()) {
|
||||||
|
List<Address> adminList = group.get().getAdmins();
|
||||||
|
final Set<Recipient> admins = new HashSet<>(adminList.size());
|
||||||
|
for (Address admin : adminList) {
|
||||||
|
admins.add(Recipient.from(getContext(), admin, false));
|
||||||
|
}
|
||||||
return Optional.of(new GroupData(groupIds[0],
|
return Optional.of(new GroupData(groupIds[0],
|
||||||
existingContacts,
|
existingContacts,
|
||||||
BitmapUtil.fromByteArray(group.get().getAvatar()),
|
BitmapUtil.fromByteArray(group.get().getAvatar()),
|
||||||
group.get().getAvatar(),
|
group.get().getAvatar(),
|
||||||
group.get().getTitle()));
|
group.get().getTitle(),
|
||||||
|
admins));
|
||||||
} else {
|
} else {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
@ -582,13 +594,15 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Bitmap avatarBmp;
|
Bitmap avatarBmp;
|
||||||
byte[] avatarBytes;
|
byte[] avatarBytes;
|
||||||
String name;
|
String name;
|
||||||
|
Set<Recipient> admins;
|
||||||
|
|
||||||
public GroupData(String id, Set<Recipient> recipients, Bitmap avatarBmp, byte[] avatarBytes, String name) {
|
public GroupData(String id, Set<Recipient> recipients, Bitmap avatarBmp, byte[] avatarBytes, String name, Set<Recipient> admins) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.recipients = recipients;
|
this.recipients = recipients;
|
||||||
this.avatarBmp = avatarBmp;
|
this.avatarBmp = avatarBmp;
|
||||||
this.avatarBytes = avatarBytes;
|
this.avatarBytes = avatarBytes;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.admins = admins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPoin
|
|||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -52,6 +51,7 @@ public class GroupDatabase extends Database {
|
|||||||
|
|
||||||
// Loki
|
// Loki
|
||||||
private static final String AVATAR_URL = "avatar_url";
|
private static final String AVATAR_URL = "avatar_url";
|
||||||
|
private static final String ADMINS = "admins";
|
||||||
|
|
||||||
public static final String CREATE_TABLE =
|
public static final String CREATE_TABLE =
|
||||||
"CREATE TABLE " + TABLE_NAME +
|
"CREATE TABLE " + TABLE_NAME +
|
||||||
@ -68,6 +68,7 @@ public class GroupDatabase extends Database {
|
|||||||
ACTIVE + " INTEGER DEFAULT 1, " +
|
ACTIVE + " INTEGER DEFAULT 1, " +
|
||||||
AVATAR_DIGEST + " BLOB, " +
|
AVATAR_DIGEST + " BLOB, " +
|
||||||
AVATAR_URL + " TEXT, " +
|
AVATAR_URL + " TEXT, " +
|
||||||
|
ADMINS + "TEXT, " +
|
||||||
MMS + " INTEGER DEFAULT 0);";
|
MMS + " INTEGER DEFAULT 0);";
|
||||||
|
|
||||||
public static final String[] CREATE_INDEXS = {
|
public static final String[] CREATE_INDEXS = {
|
||||||
@ -76,7 +77,7 @@ public class GroupDatabase extends Database {
|
|||||||
|
|
||||||
private static final String[] GROUP_PROJECTION = {
|
private static final String[] GROUP_PROJECTION = {
|
||||||
GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
|
||||||
TIMESTAMP, ACTIVE, MMS, AVATAR_URL
|
TIMESTAMP, ACTIVE, MMS, AVATAR_URL, ADMINS
|
||||||
};
|
};
|
||||||
|
|
||||||
static final List<String> TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList();
|
static final List<String> TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList();
|
||||||
@ -116,8 +117,9 @@ public class GroupDatabase extends Database {
|
|||||||
return new Reader(cursor);
|
return new Reader(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOrCreateGroupForMembers(List<Address> members, boolean mms) {
|
public String getOrCreateGroupForMembers(List<Address> members, boolean mms, List<Address> admins) {
|
||||||
Collections.sort(members);
|
Collections.sort(members);
|
||||||
|
Collections.sort(admins);
|
||||||
|
|
||||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID},
|
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID},
|
||||||
MEMBERS + " = ? AND " + MMS + " = ?",
|
MEMBERS + " = ? AND " + MMS + " = ?",
|
||||||
@ -128,7 +130,7 @@ public class GroupDatabase extends Database {
|
|||||||
return cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID));
|
return cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID));
|
||||||
} else {
|
} else {
|
||||||
String groupId = GroupUtil.getEncodedId(allocateGroupId(), mms);
|
String groupId = GroupUtil.getEncodedId(allocateGroupId(), mms);
|
||||||
create(groupId, null, members, null, null);
|
create(groupId, null, members, null, null, admins);
|
||||||
return groupId;
|
return groupId;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -157,7 +159,7 @@ public class GroupDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void create(@NonNull String groupId, @Nullable String title, @NonNull List<Address> members,
|
public void create(@NonNull String groupId, @Nullable String title, @NonNull List<Address> members,
|
||||||
@Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay)
|
@Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List<Address> admins)
|
||||||
{
|
{
|
||||||
Collections.sort(members);
|
Collections.sort(members);
|
||||||
|
|
||||||
@ -179,6 +181,10 @@ public class GroupDatabase extends Database {
|
|||||||
contentValues.put(ACTIVE, 1);
|
contentValues.put(ACTIVE, 1);
|
||||||
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
||||||
|
|
||||||
|
if (admins != null) {
|
||||||
|
contentValues.put(ADMINS, Address.toSerializedList(admins, ','));
|
||||||
|
}
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
||||||
|
|
||||||
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
||||||
@ -260,6 +266,17 @@ public class GroupDatabase extends Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateAdmins(String groupId, List<Address> admins) {
|
||||||
|
Collections.sort(admins);
|
||||||
|
|
||||||
|
ContentValues contents = new ContentValues();
|
||||||
|
contents.put(ADMINS, Address.toSerializedList(admins, ','));
|
||||||
|
contents.put(ACTIVE, 1);
|
||||||
|
|
||||||
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||||
|
new String[] {groupId});
|
||||||
|
}
|
||||||
|
|
||||||
public void remove(String groupId, Address source) {
|
public void remove(String groupId, Address source) {
|
||||||
List<Address> currentMembers = getCurrentMembers(groupId);
|
List<Address> currentMembers = getCurrentMembers(groupId);
|
||||||
currentMembers.remove(source);
|
currentMembers.remove(source);
|
||||||
@ -351,7 +368,8 @@ public class GroupDatabase extends Database {
|
|||||||
cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1,
|
cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1,
|
||||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)),
|
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)),
|
||||||
cursor.getInt(cursor.getColumnIndexOrThrow(MMS)) == 1,
|
cursor.getInt(cursor.getColumnIndexOrThrow(MMS)) == 1,
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_URL)));
|
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_URL)),
|
||||||
|
cursor.getString(cursor.getColumnIndexOrThrow(ADMINS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -375,10 +393,11 @@ public class GroupDatabase extends Database {
|
|||||||
private final boolean active;
|
private final boolean active;
|
||||||
private final boolean mms;
|
private final boolean mms;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
private final List<Address> admins;
|
||||||
|
|
||||||
public GroupRecord(String id, String title, String members, byte[] avatar,
|
public GroupRecord(String id, String title, String members, byte[] avatar,
|
||||||
long avatarId, byte[] avatarKey, String avatarContentType,
|
long avatarId, byte[] avatarKey, String avatarContentType,
|
||||||
String relay, boolean active, byte[] avatarDigest, boolean mms, String url)
|
String relay, boolean active, byte[] avatarDigest, boolean mms, String url, String admins)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
@ -394,6 +413,9 @@ public class GroupDatabase extends Database {
|
|||||||
|
|
||||||
if (!TextUtils.isEmpty(members)) this.members = Address.fromSerializedList(members, ',');
|
if (!TextUtils.isEmpty(members)) this.members = Address.fromSerializedList(members, ',');
|
||||||
else this.members = new LinkedList<>();
|
else this.members = new LinkedList<>();
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(admins)) this.admins = Address.fromSerializedList(admins, ',');
|
||||||
|
else this.admins = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getId() {
|
public byte[] getId() {
|
||||||
@ -453,5 +475,7 @@ public class GroupDatabase extends Database {
|
|||||||
public boolean isRSSFeed() { return Address.fromSerialized(id).isRSSFeed(); }
|
public boolean isRSSFeed() { return Address.fromSerialized(id).isRSSFeed(); }
|
||||||
|
|
||||||
public String getUrl() { return url; }
|
public String getUrl() { return url; }
|
||||||
|
|
||||||
|
public List<Address> getAdmins() { return admins; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ public class SmsMigrator {
|
|||||||
memberAddresses.add(recipient.getAddress());
|
memberAddresses.add(recipient.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, true);
|
String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, true, null);
|
||||||
Recipient ourGroupRecipient = Recipient.from(context, Address.fromSerialized(ourGroupId), true);
|
Recipient ourGroupRecipient = Recipient.from(context, Address.fromSerialized(ourGroupId), true);
|
||||||
long ourThreadId = threadDatabase.getThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
long ourThreadId = threadDatabase.getThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||||
|
|
||||||
|
@ -35,16 +35,19 @@ import org.thoughtcrime.securesms.database.StickerDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
|
import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.*;
|
import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.acl.Group;
|
|
||||||
|
|
||||||
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
@ -547,6 +550,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
groupUpdate.put("group_id", newId);
|
groupUpdate.put("group_id", newId);
|
||||||
db.update("groups", groupUpdate,"group_id = ?", new String[] { oldId });
|
db.update("groups", groupUpdate,"group_id = ?", new String[] { oldId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add admin field in groups
|
||||||
|
db.execSQL("ALTER TABLE groups ADD COLUMN admins TEXT");
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
|
@ -55,11 +55,12 @@ public class GroupManager {
|
|||||||
@NonNull Set<Recipient> members,
|
@NonNull Set<Recipient> members,
|
||||||
@Nullable Bitmap avatar,
|
@Nullable Bitmap avatar,
|
||||||
@Nullable String name,
|
@Nullable String name,
|
||||||
boolean mms)
|
boolean mms,
|
||||||
|
@NonNull Set<Recipient> admins)
|
||||||
{
|
{
|
||||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||||
String id = GroupUtil.getEncodedId(database.allocateGroupId(), mms);
|
String id = GroupUtil.getEncodedId(database.allocateGroupId(), mms);
|
||||||
return createGroup(id, context, members, avatar, name, mms);
|
return createGroup(id, context, members, avatar, name, mms, admins);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NonNull GroupActionResult createGroup(@NonNull String id,
|
public static @NonNull GroupActionResult createGroup(@NonNull String id,
|
||||||
@ -67,21 +68,23 @@ public class GroupManager {
|
|||||||
@NonNull Set<Recipient> members,
|
@NonNull Set<Recipient> members,
|
||||||
@Nullable Bitmap avatar,
|
@Nullable Bitmap avatar,
|
||||||
@Nullable String name,
|
@Nullable String name,
|
||||||
boolean mms)
|
boolean mms,
|
||||||
|
@NonNull Set<Recipient> admins)
|
||||||
{
|
{
|
||||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
final String groupId = GroupUtil.getEncodedId(id.getBytes(), mms);
|
final String groupId = GroupUtil.getEncodedId(id.getBytes(), mms);
|
||||||
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||||
|
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
||||||
|
|
||||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
|
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses));
|
||||||
|
|
||||||
if (!mms) {
|
if (!mms) {
|
||||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true);
|
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true);
|
||||||
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
|
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
|
||||||
} else {
|
} else {
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||||
return new GroupActionResult(groupRecipient, threadId);
|
return new GroupActionResult(groupRecipient, threadId);
|
||||||
@ -117,7 +120,7 @@ public class GroupManager {
|
|||||||
final Set<Address> memberAddresses = new HashSet<>();
|
final Set<Address> memberAddresses = new HashSet<>();
|
||||||
|
|
||||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
|
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>());
|
||||||
|
|
||||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||||
|
|
||||||
@ -129,20 +132,23 @@ public class GroupManager {
|
|||||||
@NonNull String groupId,
|
@NonNull String groupId,
|
||||||
@NonNull Set<Recipient> members,
|
@NonNull Set<Recipient> members,
|
||||||
@Nullable Bitmap avatar,
|
@Nullable Bitmap avatar,
|
||||||
@Nullable String name)
|
@Nullable String name,
|
||||||
|
@NonNull Set<Recipient> admins)
|
||||||
throws InvalidNumberException
|
throws InvalidNumberException
|
||||||
{
|
{
|
||||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||||
|
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
||||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||||
|
|
||||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||||
|
groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses));
|
||||||
groupDatabase.updateTitle(groupId, name);
|
groupDatabase.updateTitle(groupId, name);
|
||||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||||
|
|
||||||
if (!GroupUtil.isMmsGroup(groupId)) {
|
if (!GroupUtil.isMmsGroup(groupId)) {
|
||||||
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
|
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
|
||||||
} else {
|
} else {
|
||||||
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
|
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||||
@ -154,7 +160,8 @@ public class GroupManager {
|
|||||||
@NonNull String groupId,
|
@NonNull String groupId,
|
||||||
@NonNull Set<Address> members,
|
@NonNull Set<Address> members,
|
||||||
@Nullable String groupName,
|
@Nullable String groupName,
|
||||||
@Nullable byte[] avatar)
|
@Nullable byte[] avatar,
|
||||||
|
@NonNull Set<Address> admins)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Attachment avatarAttachment = null;
|
Attachment avatarAttachment = null;
|
||||||
@ -162,15 +169,20 @@ public class GroupManager {
|
|||||||
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
||||||
|
|
||||||
List<String> numbers = new LinkedList<>();
|
List<String> numbers = new LinkedList<>();
|
||||||
|
|
||||||
for (Address member : members) {
|
for (Address member : members) {
|
||||||
numbers.add(member.serialize());
|
numbers.add(member.serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> adminNumbers = new LinkedList<>();
|
||||||
|
for (Address admin : admins) {
|
||||||
|
adminNumbers.add(admin.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||||
.setType(GroupContext.Type.UPDATE)
|
.setType(GroupContext.Type.UPDATE)
|
||||||
.addAllMembers(numbers);
|
.addAllMembers(numbers)
|
||||||
|
.addAllAdmins(adminNumbers);
|
||||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||||
GroupContext groupContext = groupContextBuilder.build();
|
GroupContext groupContext = groupContextBuilder.build();
|
||||||
|
|
||||||
|
@ -25,12 +25,15 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
|||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type;
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type;
|
||||||
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
||||||
|
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -87,6 +90,7 @@ public class GroupMessageProcessor {
|
|||||||
|
|
||||||
SignalServiceAttachment avatar = group.getAvatar().orNull();
|
SignalServiceAttachment avatar = group.getAvatar().orNull();
|
||||||
List<Address> members = group.getMembers().isPresent() ? new LinkedList<Address>() : null;
|
List<Address> members = group.getMembers().isPresent() ? new LinkedList<Address>() : null;
|
||||||
|
List<Address> admins = group.getAdmins().isPresent() ? new LinkedList<>() : null;
|
||||||
|
|
||||||
if (group.getMembers().isPresent()) {
|
if (group.getMembers().isPresent()) {
|
||||||
for (String member : group.getMembers().get()) {
|
for (String member : group.getMembers().get()) {
|
||||||
@ -94,8 +98,22 @@ public class GroupMessageProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We should only create the group if we are part of the member list
|
||||||
|
String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
|
String hexEncodedPublicKey = masterHexEncodedPublicKey != null ? masterHexEncodedPublicKey : TextSecurePreferences.getLocalNumber(context);
|
||||||
|
if (members == null || !members.contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||||
|
Log.d("Loki - Group Message", "Received a group create message which doesn't include us in the member list. Ignoring.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.getAdmins().isPresent()) {
|
||||||
|
for (String admin : group.getAdmins().get()) {
|
||||||
|
admins.add(Address.fromExternal(context, admin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
database.create(id, group.getName().orNull(), members,
|
database.create(id, group.getName().orNull(), members,
|
||||||
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null);
|
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins);
|
||||||
|
|
||||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||||
}
|
}
|
||||||
@ -110,6 +128,21 @@ public class GroupMessageProcessor {
|
|||||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||||
String id = GroupUtil.getEncodedId(group);
|
String id = GroupUtil.getEncodedId(group);
|
||||||
|
|
||||||
|
// Only update group if admin sent the message
|
||||||
|
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
|
||||||
|
String sender = content.getSender();
|
||||||
|
String hexEncodedPublicKey = sender;
|
||||||
|
try {
|
||||||
|
String primaryDevice = PromiseUtil.timeout(LokiStorageAPI.shared.getPrimaryDevicePublicKey(sender), 5000).get();
|
||||||
|
if (primaryDevice != null) { hexEncodedPublicKey = primaryDevice; }
|
||||||
|
} catch (Exception e) { }
|
||||||
|
|
||||||
|
if (!groupRecord.getAdmins().contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||||
|
Log.d("Loki - Group Message", "Received a group update message from a non-admin user for " + id +". Ignoring.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Set<Address> recordMembers = new HashSet<>(groupRecord.getMembers());
|
Set<Address> recordMembers = new HashSet<>(groupRecord.getMembers());
|
||||||
Set<Address> messageMembers = new HashSet<>();
|
Set<Address> messageMembers = new HashSet<>();
|
||||||
|
|
||||||
@ -262,6 +295,10 @@ public class GroupMessageProcessor {
|
|||||||
builder.addAllMembers(group.getMembers().get());
|
builder.addAllMembers(group.getMembers().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group.getAdmins().isPresent()) {
|
||||||
|
builder.addAllAdmins(group.getAdmins().get());
|
||||||
|
}
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (members.size() > 2) {
|
if (members.size() > 2) {
|
||||||
group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true)));
|
group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true, new LinkedList<>())));
|
||||||
}
|
}
|
||||||
|
|
||||||
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false);
|
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false);
|
||||||
|
@ -267,7 +267,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
GroupContext groupContext = groupMessage.getGroupContext();
|
GroupContext groupContext = groupMessage.getGroupContext();
|
||||||
SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0);
|
SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0);
|
||||||
SignalServiceGroup.Type type = groupMessage.isGroupQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE;
|
SignalServiceGroup.Type type = groupMessage.isGroupQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE;
|
||||||
SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupType, groupContext.getName(), groupContext.getMembersList(), avatar);
|
SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupType, groupContext.getName(), groupContext.getMembersList(), avatar, groupContext.getAdminsList());
|
||||||
SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder()
|
SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder()
|
||||||
.withTimestamp(message.getSentTimeMillis())
|
.withTimestamp(message.getSentTimeMillis())
|
||||||
.withExpiration(message.getRecipient().getExpireMessages())
|
.withExpiration(message.getRecipient().getExpireMessages())
|
||||||
|
@ -97,15 +97,20 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<String> members = new LinkedList<>();
|
List<String> members = new LinkedList<>();
|
||||||
|
|
||||||
for (Address member : record.get().getMembers()) {
|
for (Address member : record.get().getMembers()) {
|
||||||
members.add(member.serialize());
|
members.add(member.serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> admins = new LinkedList<>();
|
||||||
|
for (Address admin : record.get().getAdmins()) {
|
||||||
|
admins.add(admin.serialize());
|
||||||
|
}
|
||||||
|
|
||||||
SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE)
|
SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE)
|
||||||
.withAvatar(avatar)
|
.withAvatar(avatar)
|
||||||
.withId(groupId, SignalServiceGroup.GroupType.SIGNAL)
|
.withId(groupId, SignalServiceGroup.GroupType.SIGNAL)
|
||||||
.withMembers(members)
|
.withMembers(members)
|
||||||
|
.withAdmins(admins)
|
||||||
.withName(record.get().getTitle())
|
.withName(record.get().getTitle())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.ApplicationContext
|
|||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||||
import org.thoughtcrime.securesms.database.Address
|
import org.thoughtcrime.securesms.database.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
|
||||||
import org.thoughtcrime.securesms.jobs.PushDecryptJob
|
import org.thoughtcrime.securesms.jobs.PushDecryptJob
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
@ -112,7 +111,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
// region Polling
|
// region Polling
|
||||||
private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage {
|
private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage {
|
||||||
val id = group.id.toByteArray()
|
val id = group.id.toByteArray()
|
||||||
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null)
|
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null, null)
|
||||||
val quote = if (message.quote != null) {
|
val quote = if (message.quote != null) {
|
||||||
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf())
|
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf())
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,7 +64,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF
|
|||||||
bodyAsHTML = matcher.replaceAll("$2 ($1)")
|
bodyAsHTML = matcher.replaceAll("$2 ($1)")
|
||||||
val body = Html.fromHtml(bodyAsHTML).toString().trim()
|
val body = Html.fromHtml(bodyAsHTML).toString().trim()
|
||||||
val id = feed.id.toByteArray()
|
val id = feed.id.toByteArray()
|
||||||
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null)
|
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null)
|
||||||
val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
|
val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
|
||||||
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false)
|
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false)
|
||||||
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
|
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user