mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
Add addStickerPack command
This commit is contained in:
parent
133e2cc222
commit
e867c57af8
14 changed files with 159 additions and 25 deletions
|
@ -2,6 +2,10 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- New `addStickerPack` command
|
||||
|
||||
## [0.12.0] - 2023-08-11
|
||||
**Attention**: Now requires native libsignal-client version 0.30.0
|
||||
|
||||
|
|
|
@ -211,6 +211,8 @@ public interface Manager extends Closeable {
|
|||
*/
|
||||
StickerPackUrl uploadStickerPack(File path) throws IOException, StickerPackInvalidException;
|
||||
|
||||
void installStickerPack(StickerPackUrl url) throws IOException;
|
||||
|
||||
List<StickerPack> getStickerPacks();
|
||||
|
||||
void requestAllSyncData() throws IOException;
|
||||
|
|
|
@ -22,7 +22,7 @@ public final class StickerPackUrl {
|
|||
public static StickerPackUrl fromUri(URI uri) throws InvalidStickerPackLinkException {
|
||||
final var rawQuery = uri.getRawFragment();
|
||||
if (isEmpty(rawQuery)) {
|
||||
throw new RuntimeException("Invalid sticker pack uri");
|
||||
throw new InvalidStickerPackLinkException("Invalid sticker pack uri");
|
||||
}
|
||||
|
||||
var query = Utils.getQueryMap(rawQuery);
|
||||
|
|
|
@ -585,23 +585,15 @@ public final class IncomingMessageHandler {
|
|||
continue;
|
||||
}
|
||||
final var stickerPackId = StickerPackId.deserialize(m.getPackId().get());
|
||||
final var stickerPackKey = m.getPackKey().orElse(null);
|
||||
final var installed = m.getType().isEmpty()
|
||||
|| m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
|
||||
|
||||
var sticker = account.getStickerStore().getStickerPack(stickerPackId);
|
||||
if (m.getPackKey().isPresent()) {
|
||||
if (sticker == null) {
|
||||
sticker = new StickerPack(-1, stickerPackId, m.getPackKey().get(), installed);
|
||||
account.getStickerStore().addStickerPack(sticker);
|
||||
}
|
||||
if (installed) {
|
||||
context.getJobExecutor()
|
||||
.enqueueJob(new RetrieveStickerPackJob(stickerPackId, m.getPackKey().get()));
|
||||
}
|
||||
}
|
||||
final var sticker = context.getStickerHelper()
|
||||
.addOrUpdateStickerPack(stickerPackId, stickerPackKey, installed);
|
||||
|
||||
if (sticker != null && sticker.isInstalled() != installed) {
|
||||
account.getStickerStore().updateStickerPackInstalled(sticker.packId(), installed);
|
||||
if (sticker != null && installed) {
|
||||
context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, sticker.packKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,6 +186,10 @@ public class SendHelper {
|
|||
|
||||
public SendMessageResult sendSyncMessage(SignalServiceSyncMessage message) {
|
||||
var messageSender = dependencies.getMessageSender();
|
||||
if (!account.isMultiDevice()) {
|
||||
logger.trace("Not sending sync message because there are no linked devices.");
|
||||
return SendMessageResult.success(account.getSelfAddress(), List.of(), false, false, 0, Optional.empty());
|
||||
}
|
||||
try {
|
||||
return messageSender.sendSyncMessage(message, context.getUnidentifiedAccessHelper().getAccessForSync());
|
||||
} catch (UnregisteredUserException e) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.asamk.signal.manager.api.StickerPackId;
|
|||
import org.asamk.signal.manager.internal.SignalDependencies;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
||||
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -28,16 +29,34 @@ public class StickerHelper {
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
public StickerPack addOrUpdateStickerPack(
|
||||
final StickerPackId stickerPackId, final byte[] stickerPackKey, final boolean installed
|
||||
) {
|
||||
final var sticker = account.getStickerStore().getStickerPack(stickerPackId);
|
||||
if (sticker != null) {
|
||||
if (sticker.isInstalled() != installed) {
|
||||
account.getStickerStore().updateStickerPackInstalled(sticker.packId(), installed);
|
||||
}
|
||||
return sticker;
|
||||
}
|
||||
|
||||
if (stickerPackKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final var newSticker = new StickerPack(-1, stickerPackId, stickerPackKey, installed);
|
||||
account.getStickerStore().addStickerPack(newSticker);
|
||||
return newSticker;
|
||||
}
|
||||
|
||||
public JsonStickerPack getOrRetrieveStickerPack(
|
||||
StickerPackId packId, byte[] packKey
|
||||
) throws InvalidStickerException {
|
||||
if (!context.getStickerPackStore().existsStickerPack(packId)) {
|
||||
try {
|
||||
retrieveStickerPack(packId, packKey);
|
||||
} catch (InvalidMessageException | IOException e) {
|
||||
throw new InvalidStickerException("Failed to retrieve sticker pack");
|
||||
}
|
||||
}
|
||||
final JsonStickerPack manifest;
|
||||
try {
|
||||
manifest = context.getStickerPackStore().retrieveManifest(packId);
|
||||
|
@ -48,6 +67,10 @@ public class StickerHelper {
|
|||
}
|
||||
|
||||
public void retrieveStickerPack(StickerPackId packId, byte[] packKey) throws InvalidMessageException, IOException {
|
||||
if (context.getStickerPackStore().existsStickerPack(packId)) {
|
||||
logger.debug("Sticker pack {} already downloaded.", Hex.toStringCondensed(packId.serialize()));
|
||||
return;
|
||||
}
|
||||
logger.debug("Retrieving sticker pack {}.", Hex.toStringCondensed(packId.serialize()));
|
||||
final var messageReceiver = dependencies.getMessageReceiver();
|
||||
final var manifest = messageReceiver.retrieveStickerManifest(packId.serialize(), packKey);
|
||||
|
|
|
@ -6,9 +6,11 @@ import org.asamk.signal.manager.api.TrustLevel;
|
|||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||
import org.asamk.signal.manager.util.AttachmentUtils;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.asamk.signal.manager.util.MimeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -26,6 +28,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOut
|
|||
import org.whispersystems.signalservice.api.messages.multidevice.KeysMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
|
@ -40,6 +43,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SyncHelper {
|
||||
|
||||
|
@ -222,6 +226,22 @@ public class SyncHelper {
|
|||
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage));
|
||||
}
|
||||
|
||||
public void sendStickerOperationsMessage(List<StickerPack> installStickers, List<StickerPack> removeStickers) {
|
||||
var installStickerMessages = installStickers.stream().map(s -> getStickerPackOperationMessage(s, true));
|
||||
var removeStickerMessages = removeStickers.stream().map(s -> getStickerPackOperationMessage(s, false));
|
||||
var stickerMessages = Stream.concat(installStickerMessages, removeStickerMessages).toList();
|
||||
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forStickerPackOperations(stickerMessages));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static StickerPackOperationMessage getStickerPackOperationMessage(
|
||||
final StickerPack s, final boolean installed
|
||||
) {
|
||||
return new StickerPackOperationMessage(s.packId().serialize(),
|
||||
s.packKey(),
|
||||
installed ? StickerPackOperationMessage.Type.INSTALL : StickerPackOperationMessage.Type.REMOVE);
|
||||
}
|
||||
|
||||
public void sendConfigurationMessage() {
|
||||
final var config = account.getConfigurationStore();
|
||||
var configurationMessage = new ConfigurationMessage(Optional.ofNullable(config.getReadReceipts()),
|
||||
|
|
|
@ -72,6 +72,7 @@ import org.asamk.signal.manager.util.AttachmentUtils;
|
|||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.asamk.signal.manager.util.MimeUtils;
|
||||
import org.asamk.signal.manager.util.StickerUtils;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -891,10 +892,25 @@ public class ManagerImpl implements Manager {
|
|||
|
||||
var sticker = new StickerPack(packId, packKey);
|
||||
account.getStickerStore().addStickerPack(sticker);
|
||||
context.getSyncHelper().sendStickerOperationsMessage(List.of(sticker), List.of());
|
||||
|
||||
return new StickerPackUrl(packId, packKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installStickerPack(StickerPackUrl url) throws IOException {
|
||||
final var packId = url.getPackId();
|
||||
final var packKey = url.getPackKey();
|
||||
try {
|
||||
context.getStickerHelper().retrieveStickerPack(packId, packKey);
|
||||
} catch (InvalidMessageException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
final var sticker = context.getStickerHelper().addOrUpdateStickerPack(packId, packKey, true);
|
||||
context.getSyncHelper().sendStickerOperationsMessage(List.of(sticker), List.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.asamk.signal.manager.api.StickerPack> getStickerPacks() {
|
||||
final var stickerPackStore = context.getStickerPackStore();
|
||||
|
|
|
@ -23,10 +23,6 @@ public class RetrieveStickerPackJob implements Job {
|
|||
|
||||
@Override
|
||||
public void run(Context context) {
|
||||
if (context.getStickerPackStore().existsStickerPack(packId)) {
|
||||
logger.debug("Sticker pack {} already downloaded.", Hex.toStringCondensed(packId.serialize()));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
context.getStickerHelper().retrieveStickerPack(packId, packKey);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.sql.Connection;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class StickerStore {
|
||||
|
||||
|
@ -36,7 +37,7 @@ public class StickerStore {
|
|||
this.database = database;
|
||||
}
|
||||
|
||||
public Collection<StickerPack> getStickerPacks() {
|
||||
public List<StickerPack> getStickerPacks() {
|
||||
final var sql = (
|
||||
"""
|
||||
SELECT s._id, s.pack_id, s.pack_key, s.installed
|
||||
|
|
|
@ -652,6 +652,14 @@ The path of the manifest.json or a zip file containing the sticker pack you wish
|
|||
|
||||
Show a list of known sticker packs.
|
||||
|
||||
=== addStickerPack
|
||||
|
||||
Install a sticker pack for this account.
|
||||
|
||||
*--uri* [URI]::
|
||||
Specify the uri of the sticker pack.
|
||||
e.g. https://signal.art/addstickers/#pack_id=XXX&pack_key=XXX)"
|
||||
|
||||
=== getAttachment
|
||||
|
||||
Gets the raw data for a specified attachment.
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package org.asamk.signal.commands;
|
||||
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import net.sourceforge.argparse4j.inf.Subparser;
|
||||
|
||||
import org.asamk.signal.commands.exceptions.CommandException;
|
||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.asamk.signal.manager.api.StickerPackUrl;
|
||||
import org.asamk.signal.output.OutputWriter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class AddStickerPackCommand implements JsonRpcLocalCommand {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AddStickerPackCommand.class);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "addStickerPack";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToSubparser(final Subparser subparser) {
|
||||
subparser.help("Install a sticker pack for this account.");
|
||||
subparser.addArgument("--uri")
|
||||
.required(true)
|
||||
.nargs("+")
|
||||
.help("Specify the uri of the sticker pack. (e.g. https://signal.art/addstickers/#pack_id=XXX&pack_key=XXX)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(
|
||||
final Namespace ns, final Manager m, final OutputWriter outputWriter
|
||||
) throws CommandException {
|
||||
final var uris = ns.<String>getList("uri");
|
||||
for (final var uri : uris) {
|
||||
final URI stickerUri;
|
||||
try {
|
||||
stickerUri = new URI(uri);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new UserErrorException("Sticker pack uri has invalid format: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
var stickerPackUrl = StickerPackUrl.fromUri(stickerUri);
|
||||
m.installStickerPack(stickerPackUrl);
|
||||
} catch (IOException e) {
|
||||
logger.error("Install sticker pack failed", e);
|
||||
throw new IOErrorException("Install sticker pack failed", e);
|
||||
} catch (StickerPackUrl.InvalidStickerPackLinkException e) {
|
||||
logger.error("Invalid sticker pack link", e);
|
||||
throw new UserErrorException("Invalid sticker pack link", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ public class Commands {
|
|||
addCommand(new FinishLinkCommand());
|
||||
addCommand(new GetAttachmentCommand());
|
||||
addCommand(new GetUserStatusCommand());
|
||||
addCommand(new AddStickerPackCommand());
|
||||
addCommand(new JoinGroupCommand());
|
||||
addCommand(new JsonRpcDispatcherCommand());
|
||||
addCommand(new LinkCommand());
|
||||
|
|
|
@ -481,6 +481,11 @@ public class DbusManagerImpl implements Manager {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installStickerPack(final StickerPackUrl url) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StickerPack> getStickerPacks() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue