diff --git a/CHANGELOG.md b/CHANGELOG.md index fb4e817c..a6474e6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ Requires libsignal-client version 0.86.12. - Add sendPollCreate, sendPollVote, sendPollTerminate commands for polls - 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 diff --git a/lib/src/main/java/org/asamk/signal/manager/api/ReceiveConfig.java b/lib/src/main/java/org/asamk/signal/manager/api/ReceiveConfig.java index e9108d12..f7b64e43 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/ReceiveConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/ReceiveConfig.java @@ -1,3 +1,3 @@ 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) {} diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 530076b8..e0b1cd29 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -107,7 +107,10 @@ public class GroupHelper { 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 { context.getAvatarStore() .storeGroupAvatar(groupId, @@ -167,7 +170,7 @@ public class GroupHelper { storeProfileKeysFromMembers(group); final var avatar = group.avatar; if (!avatar.isEmpty()) { - downloadGroupAvatar(groupId, groupSecretParams, avatar); + downloadGroupAvatar(groupId, groupSecretParams, avatar, false); } } groupInfoV2.setGroup(group); @@ -506,13 +509,16 @@ public class GroupHelper { storeProfileKeysFromMembers(decryptedGroup); final var avatar = decryptedGroup.avatar; if (!avatar.isEmpty()) { - downloadGroupAvatar(groupInfoV2.getGroupId(), groupSecretParams, avatar); + downloadGroupAvatar(groupInfoV2.getGroupId(), groupSecretParams, avatar, false); } groupInfoV2.setGroup(decryptedGroup); 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 { context.getAvatarStore() .storeGroupAvatar(groupId, diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java index de824b0c..992f9ddf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java @@ -369,7 +369,7 @@ public final class IncomingMessageHandler { false, senderDeviceAddress, destination, - receiveConfig.ignoreAttachments())); + receiveConfig)); } if (content.getStoryMessage().isPresent()) { @@ -382,7 +382,7 @@ public final class IncomingMessageHandler { actions.addAll(handleSyncMessage(envelope, syncMessage, senderDeviceAddress, - receiveConfig.ignoreAttachments())); + receiveConfig)); } return actions; @@ -475,7 +475,7 @@ public final class IncomingMessageHandler { final SignalServiceEnvelope envelope, final SignalServiceSyncMessage syncMessage, final DeviceAddress sender, - final boolean ignoreAttachments + final ReceiveConfig receiveConfig ) { var actions = new ArrayList(); account.setMultiDevice(true); @@ -491,12 +491,12 @@ public final class IncomingMessageHandler { : new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination), destination.getServiceId(), 0), - ignoreAttachments)); + receiveConfig)); } if (message.getStoryMessage().isPresent()) { actions.addAll(handleSignalServiceStoryMessage(message.getStoryMessage().get(), sender.recipientId(), - ignoreAttachments)); + receiveConfig.ignoreAttachments())); } } if (syncMessage.getRequest().isPresent() && account.isPrimaryDevice()) { @@ -522,7 +522,7 @@ public final class IncomingMessageHandler { try { final var groupsMessage = syncMessage.getGroups().get(); context.getAttachmentHelper() - .retrieveAttachment(groupsMessage, context.getSyncHelper()::handleSyncDeviceGroups); + .retrieveAttachment(groupsMessage, input -> context.getSyncHelper().handleSyncDeviceGroups(input, receiveConfig.ignoreAvatars())); } catch (Exception e) { 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(); context.getAttachmentHelper() .retrieveAttachment(contactsMessage.getContactsStream(), - context.getSyncHelper()::handleSyncDeviceContacts); + input -> context.getSyncHelper().handleSyncDeviceContacts(input, receiveConfig.ignoreAvatars())); } catch (Exception e) { logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage()); } @@ -576,7 +576,7 @@ public final class IncomingMessageHandler { final var sticker = context.getStickerHelper() .addOrUpdateStickerPack(stickerPackId, stickerPackKey, installed); - if (sticker != null && installed) { + if (sticker != null && installed && !receiveConfig.ignoreStickers()) { context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, sticker.packKey())); } } @@ -738,7 +738,7 @@ public final class IncomingMessageHandler { boolean isSync, DeviceAddress source, DeviceAddress destination, - boolean ignoreAttachments + ReceiveConfig receiveConfig ) { var actions = new ArrayList(); if (message.getGroupContext().isPresent()) { @@ -757,7 +757,7 @@ public final class IncomingMessageHandler { if (groupInfo.getAvatar().isPresent()) { var avatar = groupInfo.getAvatar().get(); - context.getGroupHelper().downloadGroupAvatar(groupV1.getGroupId(), avatar); + context.getGroupHelper().downloadGroupAvatar(groupV1.getGroupId(), avatar, receiveConfig.ignoreAvatars()); } if (groupInfo.getName().isPresent()) { @@ -830,7 +830,7 @@ public final class IncomingMessageHandler { message.getExpireTimerVersion()); } } - if (!ignoreAttachments) { + if (!receiveConfig.ignoreAttachments()) { if (message.getAttachments().isPresent()) { for (var attachment : message.getAttachments().get()) { context.getAttachmentHelper().downloadAttachment(attachment); @@ -878,7 +878,9 @@ public final class IncomingMessageHandler { sticker = new StickerPack(stickerPackId, messageSticker.getPackKey()); 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; } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index af16ed1d..537738ce 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -275,10 +275,13 @@ public final class ProfileHelper { private Profile decryptProfileAndDownloadAvatar( final RecipientId recipientId, final ProfileKey profileKey, - final SignalServiceProfile encryptedProfile + final SignalServiceProfile encryptedProfile, + final boolean ignoreAvatars ) { final var avatarPath = encryptedProfile.getAvatar(); - downloadProfileAvatar(recipientId, avatarPath, profileKey); + if (!ignoreAvatars) { + downloadProfileAvatar(recipientId, avatarPath, profileKey, ignoreAvatars); + } return ProfileUtils.decryptProfile(profileKey, encryptedProfile); } @@ -286,8 +289,12 @@ public final class ProfileHelper { public void downloadProfileAvatar( final RecipientId recipientId, final String avatarPath, - final ProfileKey profileKey + final ProfileKey profileKey, + final boolean ignoreAvatars ) { + if (ignoreAvatars) { + return; + } var profile = account.getProfileStore().getProfile(recipientId); if (profile == null || !Objects.equals(avatarPath, profile.getAvatarUrlPath())) { logger.trace("Downloading profile avatar for {}", recipientId); @@ -341,7 +348,7 @@ public final class ProfileHelper { Profile newProfile = null; if (profileKey.isPresent()) { logger.trace("Decrypting profile"); - newProfile = decryptProfileAndDownloadAvatar(recipientId, profileKey.get(), encryptedProfile); + newProfile = decryptProfileAndDownloadAvatar(recipientId, profileKey.get(), encryptedProfile, false); } if (newProfile == null) { diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java index add4cd82..73291d9e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java @@ -40,7 +40,7 @@ public class ReceiveHelper { private final SignalDependencies dependencies; 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 isWaitingForMessage = false; private boolean shouldStop = false; diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java index 7d553120..0030ff41 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java @@ -293,7 +293,7 @@ public class SyncHelper { 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); DeviceGroup g; while (true) { @@ -327,7 +327,7 @@ public class SyncHelper { } 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(); 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); DeviceContact c; while (true) { @@ -381,7 +381,7 @@ public class SyncHelper { account.getContactStore().storeContact(recipientId, builder.build()); if (c.getAvatar().isPresent()) { - storeContactAvatar(c.getAvatar().get(), address); + storeContactAvatar(c.getAvatar().get(), address, ignoreAvatars); } } } @@ -430,7 +430,10 @@ public class SyncHelper { streamDetails.getContentType())); } - private void storeContactAvatar(DeviceContactAvatar avatar, RecipientAddress address) { + private void storeContactAvatar(DeviceContactAvatar avatar, RecipientAddress address, boolean ignoreAvatars) { + if (ignoreAvatars) { + return; + } try { context.getAvatarStore() .storeContactAvatar(address, diff --git a/lib/src/main/java/org/asamk/signal/manager/jobs/DownloadProfileAvatarJob.java b/lib/src/main/java/org/asamk/signal/manager/jobs/DownloadProfileAvatarJob.java index f46bac0c..1971d362 100644 --- a/lib/src/main/java/org/asamk/signal/manager/jobs/DownloadProfileAvatarJob.java +++ b/lib/src/main/java/org/asamk/signal/manager/jobs/DownloadProfileAvatarJob.java @@ -18,6 +18,6 @@ public class DownloadProfileAvatarJob implements Job { logger.trace("Downloading profile avatar {}", avatarPath); final var account = context.getAccount(); context.getProfileHelper() - .downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, account.getProfileKey()); + .downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, account.getProfileKey(), false); } } diff --git a/man/signal-cli.1.adoc b/man/signal-cli.1.adoc index 0ae7a8bc..28a468fe 100644 --- a/man/signal-cli.1.adoc +++ b/man/signal-cli.1.adoc @@ -587,6 +587,12 @@ Don’t download attachments of received messages. *--ignore-stories*:: Don’t 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 for all incoming data messages (in addition to the default delivery receipts) @@ -950,6 +956,12 @@ Don’t download attachments of received messages. *--ignore-stories*:: Don’t 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 for all incoming data messages (in addition to the default delivery receipts) @@ -971,6 +983,12 @@ Don’t download attachments of received messages. *--ignore-stories*:: Don’t 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 for all incoming data messages (in addition to the default delivery receipts) diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 734f92c8..3bb05dea 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -82,6 +82,12 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand { subparser.addArgument("--ignore-stories") .help("Don’t receive story messages from the server.") .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") .help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)") .action(Arguments.storeTrue()); diff --git a/src/main/java/org/asamk/signal/commands/JsonRpcDispatcherCommand.java b/src/main/java/org/asamk/signal/commands/JsonRpcDispatcherCommand.java index 4221fa4d..2916c2c7 100644 --- a/src/main/java/org/asamk/signal/commands/JsonRpcDispatcherCommand.java +++ b/src/main/java/org/asamk/signal/commands/JsonRpcDispatcherCommand.java @@ -44,6 +44,12 @@ public class JsonRpcDispatcherCommand implements LocalCommand, MultiLocalCommand subparser.addArgument("--ignore-stories") .help("Don’t receive story messages from the server.") .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") .help("Send read receipts for all incoming data messages (in addition to the default delivery receipts)") .action(Arguments.storeTrue()); diff --git a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java index 8c3ad80c..216e5d07 100644 --- a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java +++ b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java @@ -55,6 +55,12 @@ public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand new JsonReceiveMessageHandler(m, writer); diff --git a/src/main/java/org/asamk/signal/util/CommandUtil.java b/src/main/java/org/asamk/signal/util/CommandUtil.java index 61f5013e..1875429f 100644 --- a/src/main/java/org/asamk/signal/util/CommandUtil.java +++ b/src/main/java/org/asamk/signal/util/CommandUtil.java @@ -146,8 +146,10 @@ public class CommandUtil { public static ReceiveConfig getReceiveConfig(final Namespace ns) { final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments")); 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")); - return new ReceiveConfig(ignoreAttachments, ignoreStories, sendReadReceipts); + return new ReceiveConfig(ignoreAttachments, ignoreStories, ignoreAvatars, ignoreStickers, sendReadReceipts); } }