Merge ab7f34b4460aaa4339ad65112b8d315821618943 into 06a706d070912d14d126a251cd04c2faaf19e969

This commit is contained in:
Brian Exelbierd 2026-02-04 03:17:31 -08:00 committed by GitHub
commit e5e65de02a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 90 additions and 30 deletions

View File

@ -18,6 +18,8 @@ Requires libsignal-client version 0.86.12.
- Add sendPollCreate, sendPollVote, sendPollTerminate commands for polls - Add sendPollCreate, sendPollVote, sendPollTerminate commands for polls
- Add updateDevice command to set device name of linked devices - Add updateDevice command to set device name of linked devices
- Add --ignore-avatars flag to prevent downloading avatars
- Add --ignore-stickers flag to prevent downloading sticker packs
### Changed ### Changed

View File

@ -1,3 +1,3 @@
package org.asamk.signal.manager.api; package org.asamk.signal.manager.api;
public record ReceiveConfig(boolean ignoreAttachments, boolean ignoreStories, boolean sendReadReceipts) {} public record ReceiveConfig(boolean ignoreAttachments, boolean ignoreStories, boolean ignoreAvatars, boolean ignoreStickers, boolean sendReadReceipts) {}

View File

@ -107,7 +107,10 @@ public class GroupHelper {
return group != null && group.isBlocked(); return group != null && group.isBlocked();
} }
public void downloadGroupAvatar(GroupIdV1 groupId, SignalServiceAttachment avatar) { public void downloadGroupAvatar(GroupIdV1 groupId, SignalServiceAttachment avatar, boolean ignoreAvatars) {
if (ignoreAvatars) {
return;
}
try { try {
context.getAvatarStore() context.getAvatarStore()
.storeGroupAvatar(groupId, .storeGroupAvatar(groupId,
@ -167,7 +170,7 @@ public class GroupHelper {
storeProfileKeysFromMembers(group); storeProfileKeysFromMembers(group);
final var avatar = group.avatar; final var avatar = group.avatar;
if (!avatar.isEmpty()) { if (!avatar.isEmpty()) {
downloadGroupAvatar(groupId, groupSecretParams, avatar); downloadGroupAvatar(groupId, groupSecretParams, avatar, false);
} }
} }
groupInfoV2.setGroup(group); groupInfoV2.setGroup(group);
@ -506,13 +509,16 @@ public class GroupHelper {
storeProfileKeysFromMembers(decryptedGroup); storeProfileKeysFromMembers(decryptedGroup);
final var avatar = decryptedGroup.avatar; final var avatar = decryptedGroup.avatar;
if (!avatar.isEmpty()) { if (!avatar.isEmpty()) {
downloadGroupAvatar(groupInfoV2.getGroupId(), groupSecretParams, avatar); downloadGroupAvatar(groupInfoV2.getGroupId(), groupSecretParams, avatar, false);
} }
groupInfoV2.setGroup(decryptedGroup); groupInfoV2.setGroup(decryptedGroup);
account.getGroupStore().updateGroup(group); account.getGroupStore().updateGroup(group);
} }
private void downloadGroupAvatar(GroupIdV2 groupId, GroupSecretParams groupSecretParams, String cdnKey) { private void downloadGroupAvatar(GroupIdV2 groupId, GroupSecretParams groupSecretParams, String cdnKey, boolean ignoreAvatars) {
if (ignoreAvatars) {
return;
}
try { try {
context.getAvatarStore() context.getAvatarStore()
.storeGroupAvatar(groupId, .storeGroupAvatar(groupId,

View File

@ -369,7 +369,7 @@ public final class IncomingMessageHandler {
false, false,
senderDeviceAddress, senderDeviceAddress,
destination, destination,
receiveConfig.ignoreAttachments())); receiveConfig));
} }
if (content.getStoryMessage().isPresent()) { if (content.getStoryMessage().isPresent()) {
@ -382,7 +382,7 @@ public final class IncomingMessageHandler {
actions.addAll(handleSyncMessage(envelope, actions.addAll(handleSyncMessage(envelope,
syncMessage, syncMessage,
senderDeviceAddress, senderDeviceAddress,
receiveConfig.ignoreAttachments())); receiveConfig));
} }
return actions; return actions;
@ -475,7 +475,7 @@ public final class IncomingMessageHandler {
final SignalServiceEnvelope envelope, final SignalServiceEnvelope envelope,
final SignalServiceSyncMessage syncMessage, final SignalServiceSyncMessage syncMessage,
final DeviceAddress sender, final DeviceAddress sender,
final boolean ignoreAttachments final ReceiveConfig receiveConfig
) { ) {
var actions = new ArrayList<HandleAction>(); var actions = new ArrayList<HandleAction>();
account.setMultiDevice(true); account.setMultiDevice(true);
@ -491,12 +491,12 @@ public final class IncomingMessageHandler {
: new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination), : new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
destination.getServiceId(), destination.getServiceId(),
0), 0),
ignoreAttachments)); receiveConfig));
} }
if (message.getStoryMessage().isPresent()) { if (message.getStoryMessage().isPresent()) {
actions.addAll(handleSignalServiceStoryMessage(message.getStoryMessage().get(), actions.addAll(handleSignalServiceStoryMessage(message.getStoryMessage().get(),
sender.recipientId(), sender.recipientId(),
ignoreAttachments)); receiveConfig.ignoreAttachments()));
} }
} }
if (syncMessage.getRequest().isPresent() && account.isPrimaryDevice()) { if (syncMessage.getRequest().isPresent() && account.isPrimaryDevice()) {
@ -522,7 +522,7 @@ public final class IncomingMessageHandler {
try { try {
final var groupsMessage = syncMessage.getGroups().get(); final var groupsMessage = syncMessage.getGroups().get();
context.getAttachmentHelper() context.getAttachmentHelper()
.retrieveAttachment(groupsMessage, context.getSyncHelper()::handleSyncDeviceGroups); .retrieveAttachment(groupsMessage, input -> context.getSyncHelper().handleSyncDeviceGroups(input, receiveConfig.ignoreAvatars()));
} catch (Exception e) { } catch (Exception e) {
logger.warn("Failed to handle received sync groups, ignoring: {}", e.getMessage()); logger.warn("Failed to handle received sync groups, ignoring: {}", e.getMessage());
} }
@ -550,7 +550,7 @@ public final class IncomingMessageHandler {
final var contactsMessage = syncMessage.getContacts().get(); final var contactsMessage = syncMessage.getContacts().get();
context.getAttachmentHelper() context.getAttachmentHelper()
.retrieveAttachment(contactsMessage.getContactsStream(), .retrieveAttachment(contactsMessage.getContactsStream(),
context.getSyncHelper()::handleSyncDeviceContacts); input -> context.getSyncHelper().handleSyncDeviceContacts(input, receiveConfig.ignoreAvatars()));
} catch (Exception e) { } catch (Exception e) {
logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage()); logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage());
} }
@ -576,7 +576,7 @@ public final class IncomingMessageHandler {
final var sticker = context.getStickerHelper() final var sticker = context.getStickerHelper()
.addOrUpdateStickerPack(stickerPackId, stickerPackKey, installed); .addOrUpdateStickerPack(stickerPackId, stickerPackKey, installed);
if (sticker != null && installed) { if (sticker != null && installed && !receiveConfig.ignoreStickers()) {
context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, sticker.packKey())); context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, sticker.packKey()));
} }
} }
@ -738,7 +738,7 @@ public final class IncomingMessageHandler {
boolean isSync, boolean isSync,
DeviceAddress source, DeviceAddress source,
DeviceAddress destination, DeviceAddress destination,
boolean ignoreAttachments ReceiveConfig receiveConfig
) { ) {
var actions = new ArrayList<HandleAction>(); var actions = new ArrayList<HandleAction>();
if (message.getGroupContext().isPresent()) { if (message.getGroupContext().isPresent()) {
@ -757,7 +757,7 @@ public final class IncomingMessageHandler {
if (groupInfo.getAvatar().isPresent()) { if (groupInfo.getAvatar().isPresent()) {
var avatar = groupInfo.getAvatar().get(); var avatar = groupInfo.getAvatar().get();
context.getGroupHelper().downloadGroupAvatar(groupV1.getGroupId(), avatar); context.getGroupHelper().downloadGroupAvatar(groupV1.getGroupId(), avatar, receiveConfig.ignoreAvatars());
} }
if (groupInfo.getName().isPresent()) { if (groupInfo.getName().isPresent()) {
@ -830,7 +830,7 @@ public final class IncomingMessageHandler {
message.getExpireTimerVersion()); message.getExpireTimerVersion());
} }
} }
if (!ignoreAttachments) { if (!receiveConfig.ignoreAttachments()) {
if (message.getAttachments().isPresent()) { if (message.getAttachments().isPresent()) {
for (var attachment : message.getAttachments().get()) { for (var attachment : message.getAttachments().get()) {
context.getAttachmentHelper().downloadAttachment(attachment); context.getAttachmentHelper().downloadAttachment(attachment);
@ -878,7 +878,9 @@ public final class IncomingMessageHandler {
sticker = new StickerPack(stickerPackId, messageSticker.getPackKey()); sticker = new StickerPack(stickerPackId, messageSticker.getPackKey());
account.getStickerStore().addStickerPack(sticker); account.getStickerStore().addStickerPack(sticker);
} }
context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey())); if (!receiveConfig.ignoreStickers()) {
context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey()));
}
} }
return actions; return actions;
} }

View File

@ -275,10 +275,13 @@ public final class ProfileHelper {
private Profile decryptProfileAndDownloadAvatar( private Profile decryptProfileAndDownloadAvatar(
final RecipientId recipientId, final RecipientId recipientId,
final ProfileKey profileKey, final ProfileKey profileKey,
final SignalServiceProfile encryptedProfile final SignalServiceProfile encryptedProfile,
final boolean ignoreAvatars
) { ) {
final var avatarPath = encryptedProfile.getAvatar(); final var avatarPath = encryptedProfile.getAvatar();
downloadProfileAvatar(recipientId, avatarPath, profileKey); if (!ignoreAvatars) {
downloadProfileAvatar(recipientId, avatarPath, profileKey, ignoreAvatars);
}
return ProfileUtils.decryptProfile(profileKey, encryptedProfile); return ProfileUtils.decryptProfile(profileKey, encryptedProfile);
} }
@ -286,8 +289,12 @@ public final class ProfileHelper {
public void downloadProfileAvatar( public void downloadProfileAvatar(
final RecipientId recipientId, final RecipientId recipientId,
final String avatarPath, final String avatarPath,
final ProfileKey profileKey final ProfileKey profileKey,
final boolean ignoreAvatars
) { ) {
if (ignoreAvatars) {
return;
}
var profile = account.getProfileStore().getProfile(recipientId); var profile = account.getProfileStore().getProfile(recipientId);
if (profile == null || !Objects.equals(avatarPath, profile.getAvatarUrlPath())) { if (profile == null || !Objects.equals(avatarPath, profile.getAvatarUrlPath())) {
logger.trace("Downloading profile avatar for {}", recipientId); logger.trace("Downloading profile avatar for {}", recipientId);
@ -341,7 +348,7 @@ public final class ProfileHelper {
Profile newProfile = null; Profile newProfile = null;
if (profileKey.isPresent()) { if (profileKey.isPresent()) {
logger.trace("Decrypting profile"); logger.trace("Decrypting profile");
newProfile = decryptProfileAndDownloadAvatar(recipientId, profileKey.get(), encryptedProfile); newProfile = decryptProfileAndDownloadAvatar(recipientId, profileKey.get(), encryptedProfile, false);
} }
if (newProfile == null) { if (newProfile == null) {

View File

@ -40,7 +40,7 @@ public class ReceiveHelper {
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final Context context; private final Context context;
private ReceiveConfig receiveConfig = new ReceiveConfig(false, false, false); private ReceiveConfig receiveConfig = new ReceiveConfig(false, false, false, false, false);
private boolean hasCaughtUpWithOldMessages = false; private boolean hasCaughtUpWithOldMessages = false;
private boolean isWaitingForMessage = false; private boolean isWaitingForMessage = false;
private boolean shouldStop = false; private boolean shouldStop = false;

View File

@ -293,7 +293,7 @@ public class SyncHelper {
return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage)); return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
} }
public void handleSyncDeviceGroups(final InputStream input) { public void handleSyncDeviceGroups(final InputStream input, final boolean ignoreAvatars) {
final var s = new DeviceGroupsInputStream(input); final var s = new DeviceGroupsInputStream(input);
DeviceGroup g; DeviceGroup g;
while (true) { while (true) {
@ -327,7 +327,7 @@ public class SyncHelper {
} }
if (g.getAvatar().isPresent()) { if (g.getAvatar().isPresent()) {
context.getGroupHelper().downloadGroupAvatar(syncGroup.getGroupId(), g.getAvatar().get()); context.getGroupHelper().downloadGroupAvatar(syncGroup.getGroupId(), g.getAvatar().get(), ignoreAvatars);
} }
syncGroup.archived = g.isArchived(); syncGroup.archived = g.isArchived();
account.getGroupStore().updateGroup(syncGroup); account.getGroupStore().updateGroup(syncGroup);
@ -335,7 +335,7 @@ public class SyncHelper {
} }
} }
public void handleSyncDeviceContacts(final InputStream input) throws IOException { public void handleSyncDeviceContacts(final InputStream input, final boolean ignoreAvatars) throws IOException {
final var s = new DeviceContactsInputStream(input); final var s = new DeviceContactsInputStream(input);
DeviceContact c; DeviceContact c;
while (true) { while (true) {
@ -381,7 +381,7 @@ public class SyncHelper {
account.getContactStore().storeContact(recipientId, builder.build()); account.getContactStore().storeContact(recipientId, builder.build());
if (c.getAvatar().isPresent()) { if (c.getAvatar().isPresent()) {
storeContactAvatar(c.getAvatar().get(), address); storeContactAvatar(c.getAvatar().get(), address, ignoreAvatars);
} }
} }
} }
@ -430,7 +430,10 @@ public class SyncHelper {
streamDetails.getContentType())); streamDetails.getContentType()));
} }
private void storeContactAvatar(DeviceContactAvatar avatar, RecipientAddress address) { private void storeContactAvatar(DeviceContactAvatar avatar, RecipientAddress address, boolean ignoreAvatars) {
if (ignoreAvatars) {
return;
}
try { try {
context.getAvatarStore() context.getAvatarStore()
.storeContactAvatar(address, .storeContactAvatar(address,

View File

@ -18,6 +18,6 @@ public class DownloadProfileAvatarJob implements Job {
logger.trace("Downloading profile avatar {}", avatarPath); logger.trace("Downloading profile avatar {}", avatarPath);
final var account = context.getAccount(); final var account = context.getAccount();
context.getProfileHelper() context.getProfileHelper()
.downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, account.getProfileKey()); .downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, account.getProfileKey(), false);
} }
} }

View File

@ -587,6 +587,12 @@ Dont download attachments of received messages.
*--ignore-stories*:: *--ignore-stories*::
Dont receive story messages from the server. Dont receive story messages from the server.
*--ignore-avatars*::
Don't download avatars of received messages.
*--ignore-stickers*::
Don't download sticker packs of received messages.
*--send-read-receipts*:: *--send-read-receipts*::
Send read receipts for all incoming data messages (in addition to the default delivery receipts) Send read receipts for all incoming data messages (in addition to the default delivery receipts)
@ -950,6 +956,12 @@ Dont download attachments of received messages.
*--ignore-stories*:: *--ignore-stories*::
Dont receive story messages from the server. Dont receive story messages from the server.
*--ignore-avatars*::
Don't download avatars of received messages.
*--ignore-stickers*::
Don't download sticker packs of received messages.
*--send-read-receipts*:: *--send-read-receipts*::
Send read receipts for all incoming data messages (in addition to the default delivery receipts) Send read receipts for all incoming data messages (in addition to the default delivery receipts)
@ -971,6 +983,12 @@ Dont download attachments of received messages.
*--ignore-stories*:: *--ignore-stories*::
Dont receive story messages from the server. Dont receive story messages from the server.
*--ignore-avatars*::
Don't download avatars of received messages.
*--ignore-stickers*::
Don't download sticker packs of received messages.
*--send-read-receipts*:: *--send-read-receipts*::
Send read receipts for all incoming data messages (in addition to the default delivery receipts) Send read receipts for all incoming data messages (in addition to the default delivery receipts)

View File

@ -82,6 +82,12 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
subparser.addArgument("--ignore-stories") subparser.addArgument("--ignore-stories")
.help("Dont receive story messages from the server.") .help("Dont receive story messages from the server.")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());
subparser.addArgument("--ignore-avatars")
.help("Don't download avatars of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--ignore-stickers")
.help("Don't download sticker packs of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--send-read-receipts") subparser.addArgument("--send-read-receipts")
.help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)") .help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());

View File

@ -44,6 +44,12 @@ public class JsonRpcDispatcherCommand implements LocalCommand, MultiLocalCommand
subparser.addArgument("--ignore-stories") subparser.addArgument("--ignore-stories")
.help("Dont receive story messages from the server.") .help("Dont receive story messages from the server.")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());
subparser.addArgument("--ignore-avatars")
.help("Don't download avatars of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--ignore-stickers")
.help("Don't download sticker packs of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--send-read-receipts") subparser.addArgument("--send-read-receipts")
.help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)") .help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());

View File

@ -55,6 +55,12 @@ public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand<Receiv
subparser.addArgument("--ignore-stories") subparser.addArgument("--ignore-stories")
.help("Dont receive story messages from the server.") .help("Dont receive story messages from the server.")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());
subparser.addArgument("--ignore-avatars")
.help("Don't download avatars of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--ignore-stickers")
.help("Don't download sticker packs of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--send-read-receipts") subparser.addArgument("--send-read-receipts")
.help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)") .help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)")
.action(Arguments.storeTrue()); .action(Arguments.storeTrue());
@ -76,8 +82,10 @@ public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand<Receiv
final var maxMessagesRaw = ns.getInt("max-messages"); final var maxMessagesRaw = ns.getInt("max-messages");
final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments")); final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories")); final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories"));
final var ignoreAvatars = Boolean.TRUE.equals(ns.getBoolean("ignore-avatars"));
final var ignoreStickers = Boolean.TRUE.equals(ns.getBoolean("ignore-stickers"));
final var sendReadReceipts = Boolean.TRUE.equals(ns.getBoolean("send-read-receipts")); final var sendReadReceipts = Boolean.TRUE.equals(ns.getBoolean("send-read-receipts"));
m.setReceiveConfig(new ReceiveConfig(ignoreAttachments, ignoreStories, sendReadReceipts)); m.setReceiveConfig(new ReceiveConfig(ignoreAttachments, ignoreStories, ignoreAvatars, ignoreStickers, sendReadReceipts));
try { try {
final var handler = switch (outputWriter) { final var handler = switch (outputWriter) {
case JsonWriter writer -> new JsonReceiveMessageHandler(m, writer); case JsonWriter writer -> new JsonReceiveMessageHandler(m, writer);

View File

@ -146,8 +146,10 @@ public class CommandUtil {
public static ReceiveConfig getReceiveConfig(final Namespace ns) { public static ReceiveConfig getReceiveConfig(final Namespace ns) {
final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments")); final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories")); final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories"));
final var ignoreAvatars = Boolean.TRUE.equals(ns.getBoolean("ignore-avatars"));
final var ignoreStickers = Boolean.TRUE.equals(ns.getBoolean("ignore-stickers"));
final var sendReadReceipts = Boolean.TRUE.equals(ns.getBoolean("send-read-receipts")); final var sendReadReceipts = Boolean.TRUE.equals(ns.getBoolean("send-read-receipts"));
return new ReceiveConfig(ignoreAttachments, ignoreStories, sendReadReceipts); return new ReceiveConfig(ignoreAttachments, ignoreStories, ignoreAvatars, ignoreStickers, sendReadReceipts);
} }
} }