mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-25 19:29:54 +01:00
Move all files to natural position.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package org.thoughtcrime.securesms.groups;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class GroupManager {
|
||||
|
||||
public static @NonNull GroupActionResult createGroup(@NonNull Context context,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name,
|
||||
boolean mms)
|
||||
{
|
||||
Set<RecipientId> addresses = getMemberIds(members);
|
||||
|
||||
return V1GroupManager.createGroup(context, addresses, avatar, name, mms);
|
||||
}
|
||||
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
Set<RecipientId> addresses = getMemberIds(members);
|
||||
|
||||
return V1GroupManager.updateGroup(context, groupId, addresses, avatar, name);
|
||||
}
|
||||
|
||||
private static Set<RecipientId> getMemberIds(Collection<Recipient> recipients) {
|
||||
final Set<RecipientId> results = new HashSet<>();
|
||||
for (Recipient recipient : recipients) {
|
||||
results.add(recipient.getId());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static class GroupActionResult {
|
||||
private final Recipient groupRecipient;
|
||||
private final long threadId;
|
||||
|
||||
public GroupActionResult(Recipient groupRecipient, long threadId) {
|
||||
this.groupRecipient = groupRecipient;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public Recipient getGroupRecipient() {
|
||||
return groupRecipient;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
package org.thoughtcrime.securesms.groups;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
public class GroupMessageProcessor {
|
||||
|
||||
private static final String TAG = GroupMessageProcessor.class.getSimpleName();
|
||||
|
||||
public static @Nullable Long process(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
boolean outgoing)
|
||||
{
|
||||
if (!message.getGroupInfo().isPresent() || message.getGroupInfo().get().getGroupId() == null) {
|
||||
Log.w(TAG, "Received group message with no id! Ignoring...");
|
||||
return null;
|
||||
}
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalServiceGroup group = message.getGroupInfo().get();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
Optional<GroupRecord> record = database.getGroup(id);
|
||||
|
||||
if (record.isPresent() && group.getType() == Type.UPDATE) {
|
||||
return handleGroupUpdate(context, content, group, record.get(), outgoing);
|
||||
} else if (!record.isPresent() && group.getType() == Type.UPDATE) {
|
||||
return handleGroupCreate(context, content, group, outgoing);
|
||||
} else if (record.isPresent() && group.getType() == Type.QUIT) {
|
||||
return handleGroupLeave(context, content, group, record.get(), outgoing);
|
||||
} else if (record.isPresent() && group.getType() == Type.REQUEST_INFO) {
|
||||
return handleGroupInfoRequest(context, content, group, record.get());
|
||||
} else {
|
||||
Log.w(TAG, "Received unknown type, ignoring...");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Long handleGroupCreate(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroup group,
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.UPDATE);
|
||||
|
||||
SignalServiceAttachment avatar = group.getAvatar().orNull();
|
||||
List<RecipientId> members = new LinkedList<>();
|
||||
|
||||
if (group.getMembers().isPresent()) {
|
||||
for (SignalServiceAddress member : group.getMembers().get()) {
|
||||
members.add(Recipient.externalPush(context, member).getId());
|
||||
}
|
||||
}
|
||||
|
||||
database.create(id, group.getName().orNull(), members,
|
||||
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null);
|
||||
|
||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||
}
|
||||
|
||||
private static @Nullable Long handleGroupUpdate(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroup group,
|
||||
@NonNull GroupRecord groupRecord,
|
||||
boolean outgoing)
|
||||
{
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
|
||||
Set<RecipientId> recordMembers = new HashSet<>(groupRecord.getMembers());
|
||||
Set<RecipientId> messageMembers = new HashSet<>();
|
||||
|
||||
for (SignalServiceAddress messageMember : group.getMembers().get()) {
|
||||
messageMembers.add(Recipient.externalPush(context, messageMember).getId());
|
||||
}
|
||||
|
||||
Set<RecipientId> addedMembers = new HashSet<>(messageMembers);
|
||||
addedMembers.removeAll(recordMembers);
|
||||
|
||||
Set<RecipientId> missingMembers = new HashSet<>(recordMembers);
|
||||
missingMembers.removeAll(messageMembers);
|
||||
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.UPDATE);
|
||||
|
||||
if (addedMembers.size() > 0) {
|
||||
Set<RecipientId> unionMembers = new HashSet<>(recordMembers);
|
||||
unionMembers.addAll(messageMembers);
|
||||
database.updateMembers(id, new LinkedList<>(unionMembers));
|
||||
|
||||
builder.clearMembers();
|
||||
|
||||
for (RecipientId addedMember : addedMembers) {
|
||||
Recipient recipient = Recipient.resolved(addedMember);
|
||||
|
||||
if (recipient.getE164().isPresent()) {
|
||||
builder.addMembersE164(recipient.getE164().get());
|
||||
}
|
||||
|
||||
builder.addMembers(createMember(RecipientUtil.toSignalServiceAddress(context, recipient)));
|
||||
}
|
||||
} else {
|
||||
builder.clearMembers();
|
||||
}
|
||||
|
||||
if (missingMembers.size() > 0) {
|
||||
// TODO We should tell added and missing about each-other.
|
||||
}
|
||||
|
||||
if (group.getName().isPresent() || group.getAvatar().isPresent()) {
|
||||
SignalServiceAttachment avatar = group.getAvatar().orNull();
|
||||
database.update(id, group.getName().orNull(), avatar != null ? avatar.asPointer() : null);
|
||||
}
|
||||
|
||||
if (group.getName().isPresent() && group.getName().get().equals(groupRecord.getTitle())) {
|
||||
builder.clearName();
|
||||
}
|
||||
|
||||
if (!groupRecord.isActive()) database.setActive(id, true);
|
||||
|
||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||
}
|
||||
|
||||
private static Long handleGroupInfoRequest(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroup group,
|
||||
@NonNull GroupRecord record)
|
||||
{
|
||||
Recipient sender = Recipient.externalPush(context, content.getSender());
|
||||
|
||||
if (record.getMembers().contains(sender.getId())) {
|
||||
ApplicationDependencies.getJobManager().add(new PushGroupUpdateJob(sender.getId(), group.getGroupId()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Long handleGroupLeave(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroup group,
|
||||
@NonNull GroupRecord record,
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
List<RecipientId> members = record.getMembers();
|
||||
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.QUIT);
|
||||
|
||||
if (members.contains(Recipient.externalPush(context, content.getSender()).getId())) {
|
||||
database.remove(id, Recipient.externalPush(context, content.getSender()).getId());
|
||||
if (outgoing) database.setActive(id, false);
|
||||
|
||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static @Nullable Long storeMessage(@NonNull Context context,
|
||||
@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroup group,
|
||||
@NonNull GroupContext storage,
|
||||
boolean outgoing)
|
||||
{
|
||||
if (group.getAvatar().isPresent()) {
|
||||
ApplicationDependencies.getJobManager()
|
||||
.add(new AvatarDownloadJob(group.getGroupId()));
|
||||
}
|
||||
|
||||
try {
|
||||
if (outgoing) {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
RecipientId recipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(GroupUtil.getEncodedId(group.getGroupId(), false));
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, content.getTimestamp(), 0, false, null, Collections.emptyList(), Collections.emptyList());
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);
|
||||
|
||||
mmsDatabase.markAsSent(messageId, true);
|
||||
|
||||
return threadId;
|
||||
} else {
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
String body = Base64.encodeBytes(storage.toByteArray());
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), body, Optional.of(GroupUtil.getEncodedId(group.getGroupId(), false)), 0, content.isNeedsReceipt());
|
||||
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
|
||||
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
||||
return insertResult.get().getThreadId();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static GroupContext.Builder createGroupContext(SignalServiceGroup group) {
|
||||
GroupContext.Builder builder = GroupContext.newBuilder();
|
||||
builder.setId(ByteString.copyFrom(group.getGroupId()));
|
||||
|
||||
if (group.getAvatar().isPresent() && group.getAvatar().get().isPointer()) {
|
||||
builder.setAvatar(AttachmentPointer.newBuilder()
|
||||
.setId(group.getAvatar().get().asPointer().getId())
|
||||
.setKey(ByteString.copyFrom(group.getAvatar().get().asPointer().getKey()))
|
||||
.setContentType(group.getAvatar().get().getContentType()));
|
||||
}
|
||||
|
||||
if (group.getName().isPresent()) {
|
||||
builder.setName(group.getName().get());
|
||||
}
|
||||
|
||||
if (group.getMembers().isPresent()) {
|
||||
builder.addAllMembersE164(Stream.of(group.getMembers().get())
|
||||
.filter(a -> a.getNumber().isPresent())
|
||||
.map(a -> a.getNumber().get())
|
||||
.toList());
|
||||
builder.addAllMembers(Stream.of(group.getMembers().get())
|
||||
.map(GroupMessageProcessor::createMember)
|
||||
.toList());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static GroupContext.Member createMember(SignalServiceAddress address) {
|
||||
GroupContext.Member.Builder member = GroupContext.Member.newBuilder();
|
||||
|
||||
if (address.getUuid().isPresent()) {
|
||||
member = member.setUuid(address.getUuid().get().toString());
|
||||
}
|
||||
|
||||
if (address.getNumber().isPresent()) {
|
||||
member = member.setE164(address.getNumber().get());
|
||||
}
|
||||
|
||||
return member.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package org.thoughtcrime.securesms.groups;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHash;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
final class V1GroupManager {
|
||||
|
||||
static @NonNull GroupActionResult createGroup(@NonNull Context context,
|
||||
@NonNull Set<RecipientId> memberIds,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name,
|
||||
boolean mms)
|
||||
{
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final String groupId = GroupUtil.getEncodedId(groupDatabase.allocateGroupId(), mms);
|
||||
final RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId);
|
||||
final Recipient groupRecipient = Recipient.resolved(groupRecipientId);
|
||||
|
||||
memberIds.add(Recipient.self().getId());
|
||||
groupDatabase.create(groupId, name, new LinkedList<>(memberIds), null, null);
|
||||
|
||||
if (!mms) {
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient.getId(), true);
|
||||
return sendGroupUpdate(context, groupId, memberIds, name, avatarBytes);
|
||||
} else {
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<RecipientId> memberAddresses,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
|
||||
memberAddresses.add(Recipient.self().getId());
|
||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||
groupDatabase.updateTitle(groupId, name);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
if (!GroupUtil.isMmsGroup(groupId)) {
|
||||
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId);
|
||||
Recipient groupRecipient = Recipient.resolved(groupRecipientId);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<RecipientId> members,
|
||||
@Nullable String groupName,
|
||||
@Nullable byte[] avatar)
|
||||
{
|
||||
try {
|
||||
Attachment avatarAttachment = null;
|
||||
RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId);
|
||||
Recipient groupRecipient = Recipient.resolved(groupRecipientId);
|
||||
|
||||
List<GroupContext.Member> uuidMembers = new LinkedList<>();
|
||||
List<String> e164Members = new LinkedList<>();
|
||||
|
||||
for (RecipientId member : members) {
|
||||
Recipient recipient = Recipient.resolved(member);
|
||||
uuidMembers.add(GroupMessageProcessor.createMember(RecipientUtil.toSignalServiceAddress(context, recipient)));
|
||||
}
|
||||
|
||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||
.setType(GroupContext.Type.UPDATE)
|
||||
.addAllMembersE164(e164Members)
|
||||
.addAllMembers(uuidMembers);
|
||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||
GroupContext groupContext = groupContextBuilder.build();
|
||||
|
||||
if (avatar != null) {
|
||||
Uri avatarUri = BlobProvider.getInstance().forData(avatar).createForSingleUseInMemory();
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false, null, null, null, null);
|
||||
}
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0, false, null, Collections.emptyList(), Collections.emptyList());
|
||||
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user