2015-11-05 18:41:43 +00:00
|
|
|
package org.thoughtcrime.securesms.groups;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.support.annotation.NonNull;
|
|
|
|
import android.support.annotation.Nullable;
|
|
|
|
|
|
|
|
import com.google.protobuf.ByteString;
|
|
|
|
|
|
|
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
|
|
|
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
|
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
|
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
|
|
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
|
|
|
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
|
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
|
|
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
|
|
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
|
|
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
|
|
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
2017-05-08 22:32:59 +00:00
|
|
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
2015-11-05 18:41:43 +00:00
|
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
|
|
import org.thoughtcrime.securesms.util.Util;
|
2016-03-23 17:34:41 +00:00
|
|
|
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|
|
|
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
2015-11-05 18:41:43 +00:00
|
|
|
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
public class GroupManager {
|
|
|
|
public static @NonNull GroupActionResult createGroup(@NonNull Context context,
|
|
|
|
@NonNull MasterSecret masterSecret,
|
|
|
|
@NonNull Set<Recipient> members,
|
|
|
|
@Nullable Bitmap avatar,
|
|
|
|
@Nullable String name)
|
|
|
|
throws InvalidNumberException
|
|
|
|
{
|
|
|
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
|
|
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
|
|
|
final byte[] groupId = groupDatabase.allocateGroupId();
|
|
|
|
final Set<String> memberE164Numbers = getE164Numbers(context, members);
|
|
|
|
|
|
|
|
memberE164Numbers.add(TextSecurePreferences.getLocalNumber(context));
|
|
|
|
groupDatabase.create(groupId, name, new LinkedList<>(memberE164Numbers), null, null);
|
|
|
|
groupDatabase.updateAvatar(groupId, avatarBytes);
|
|
|
|
return sendGroupUpdate(context, masterSecret, groupId, memberE164Numbers, name, avatarBytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Set<String> getE164Numbers(Context context, Collection<Recipient> recipients)
|
|
|
|
throws InvalidNumberException
|
|
|
|
{
|
|
|
|
final Set<String> results = new HashSet<>();
|
|
|
|
for (Recipient recipient : recipients) {
|
|
|
|
results.add(Util.canonicalizeNumber(context, recipient.getNumber()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static GroupActionResult updateGroup(@NonNull Context context,
|
|
|
|
@NonNull MasterSecret masterSecret,
|
|
|
|
@NonNull byte[] groupId,
|
|
|
|
@NonNull Set<Recipient> members,
|
|
|
|
@Nullable Bitmap avatar,
|
|
|
|
@Nullable String name)
|
|
|
|
throws InvalidNumberException
|
|
|
|
{
|
|
|
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
|
|
|
final Set<String> memberE164Numbers = getE164Numbers(context, members);
|
|
|
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
|
|
|
|
|
|
|
memberE164Numbers.add(TextSecurePreferences.getLocalNumber(context));
|
|
|
|
groupDatabase.updateMembers(groupId, new LinkedList<>(memberE164Numbers));
|
|
|
|
groupDatabase.updateTitle(groupId, name);
|
|
|
|
groupDatabase.updateAvatar(groupId, avatarBytes);
|
|
|
|
|
|
|
|
return sendGroupUpdate(context, masterSecret, groupId, memberE164Numbers, name, avatarBytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
|
|
|
@NonNull MasterSecret masterSecret,
|
|
|
|
@NonNull byte[] groupId,
|
|
|
|
@NonNull Set<String> e164numbers,
|
|
|
|
@Nullable String groupName,
|
|
|
|
@Nullable byte[] avatar)
|
|
|
|
{
|
|
|
|
Attachment avatarAttachment = null;
|
|
|
|
String groupRecipientId = GroupUtil.getEncodedId(groupId);
|
|
|
|
Recipients groupRecipient = RecipientFactory.getRecipientsFromString(context, groupRecipientId, false);
|
|
|
|
|
|
|
|
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
|
|
|
.setId(ByteString.copyFrom(groupId))
|
|
|
|
.setType(GroupContext.Type.UPDATE)
|
|
|
|
.addAllMembers(e164numbers);
|
|
|
|
if (groupName != null) groupContextBuilder.setName(groupName);
|
|
|
|
GroupContext groupContext = groupContextBuilder.build();
|
|
|
|
|
|
|
|
if (avatar != null) {
|
|
|
|
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
|
2017-05-12 05:46:35 +00:00
|
|
|
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false);
|
2015-11-05 18:41:43 +00:00
|
|
|
}
|
|
|
|
|
2016-08-16 03:23:56 +00:00
|
|
|
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);
|
2017-04-22 23:29:26 +00:00
|
|
|
long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false, null);
|
2015-11-05 18:41:43 +00:00
|
|
|
|
|
|
|
return new GroupActionResult(groupRecipient, threadId);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class GroupActionResult {
|
|
|
|
private Recipients groupRecipient;
|
|
|
|
private long threadId;
|
|
|
|
|
|
|
|
public GroupActionResult(Recipients groupRecipient, long threadId) {
|
|
|
|
this.groupRecipient = groupRecipient;
|
|
|
|
this.threadId = threadId;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Recipients getGroupRecipient() {
|
|
|
|
return groupRecipient;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getThreadId() {
|
|
|
|
return threadId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|