Add sticker pack url to list output

This commit is contained in:
AsamK 2022-01-03 18:50:27 +01:00
parent 99eef05084
commit 8a5f98dac6
10 changed files with 133 additions and 44 deletions

View file

@ -1,18 +1,16 @@
package org.asamk.signal.manager;
import org.asamk.signal.manager.api.InvalidDeviceLinkException;
import org.asamk.signal.manager.util.Utils;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.ecc.Curve;
import org.whispersystems.libsignal.ecc.ECPublicKey;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
@ -24,7 +22,7 @@ public record DeviceLinkInfo(String deviceIdentifier, ECPublicKey deviceKey) {
throw new RuntimeException("Invalid device link uri");
}
var query = getQueryMap(rawQuery);
var query = Utils.getQueryMap(rawQuery);
var deviceIdentifier = query.get("uuid");
var publicKeyEncoded = query.get("pub_key");
@ -48,18 +46,6 @@ public record DeviceLinkInfo(String deviceIdentifier, ECPublicKey deviceKey) {
return new DeviceLinkInfo(deviceIdentifier, deviceKey);
}
private static Map<String, String> getQueryMap(String query) {
var params = query.split("&");
var map = new HashMap<String, String>();
for (var param : params) {
final var paramParts = param.split("=");
var name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8);
var value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8);
map.put(name, value);
}
return map;
}
public URI createDeviceLinkUri() {
final var deviceKeyString = Base64.getEncoder().encodeToString(deviceKey.serialize()).replace("=", "");
try {

View file

@ -14,6 +14,7 @@ import org.asamk.signal.manager.api.RecipientIdentifier;
import org.asamk.signal.manager.api.SendGroupMessageResults;
import org.asamk.signal.manager.api.SendMessageResults;
import org.asamk.signal.manager.api.StickerPack;
import org.asamk.signal.manager.api.StickerPackUrl;
import org.asamk.signal.manager.api.TypingAction;
import org.asamk.signal.manager.api.UnregisteredRecipientException;
import org.asamk.signal.manager.api.UpdateGroup;
@ -220,7 +221,7 @@ public interface Manager extends Closeable {
* @param path Path can be a path to a manifest.json file or to a zip file that contains a manifest.json file
* @return if successful, returns the URL to install the sticker pack in the signal app
*/
URI uploadStickerPack(File path) throws IOException, StickerPackInvalidException;
StickerPackUrl uploadStickerPack(File path) throws IOException, StickerPackInvalidException;
List<StickerPack> getStickerPacks();

View file

@ -31,6 +31,7 @@ import org.asamk.signal.manager.api.SendMessageResult;
import org.asamk.signal.manager.api.SendMessageResults;
import org.asamk.signal.manager.api.StickerPack;
import org.asamk.signal.manager.api.StickerPackId;
import org.asamk.signal.manager.api.StickerPackUrl;
import org.asamk.signal.manager.api.TypingAction;
import org.asamk.signal.manager.api.UnregisteredRecipientException;
import org.asamk.signal.manager.api.UpdateGroup;
@ -70,9 +71,6 @@ import org.whispersystems.signalservice.internal.util.Util;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
@ -658,7 +656,7 @@ public class ManagerImpl implements Manager {
}
@Override
public URI uploadStickerPack(File path) throws IOException, StickerPackInvalidException {
public StickerPackUrl uploadStickerPack(File path) throws IOException, StickerPackInvalidException {
var manifest = StickerUtils.getSignalServiceStickerManifestUpload(path);
var messageSender = dependencies.getMessageSender();
@ -670,17 +668,7 @@ public class ManagerImpl implements Manager {
var sticker = new Sticker(packId, packKey);
account.getStickerStore().updateSticker(sticker);
try {
return new URI("https",
"signal.art",
"/addstickers/",
"pack_id="
+ URLEncoder.encode(Hex.toStringCondensed(packId.serialize()), StandardCharsets.UTF_8)
+ "&pack_key="
+ URLEncoder.encode(Hex.toStringCondensed(packKey), StandardCharsets.UTF_8));
} catch (URISyntaxException e) {
throw new AssertionError(e);
}
return new StickerPackUrl(packId, packKey);
}
@Override
@ -691,7 +679,7 @@ public class ManagerImpl implements Manager {
try {
final var manifest = stickerPackStore.retrieveManifest(pack.getPackId());
return new StickerPack(pack.getPackId(),
pack.getPackKey(),
new StickerPackUrl(pack.getPackId(), pack.getPackKey()),
pack.isInstalled(),
manifest.title(),
manifest.author(),

View file

@ -5,7 +5,7 @@ import java.util.Optional;
public record StickerPack(
StickerPackId packId,
byte[] packKey,
StickerPackUrl url,
boolean installed,
String title,
String author,
@ -14,7 +14,7 @@ public record StickerPack(
) {
public StickerPack(final StickerPackId packId, final byte[] packKey, final boolean installed) {
this(packId, packKey, installed, "", "", Optional.empty(), List.of());
this(packId, new StickerPackUrl(packId, packKey), installed, "", "", Optional.empty(), List.of());
}
public record Sticker(int id, String emoji, String contentType) {}

View file

@ -0,0 +1,88 @@
package org.asamk.signal.manager.api;
import org.asamk.signal.manager.util.Utils;
import org.whispersystems.signalservice.internal.util.Hex;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
public final class StickerPackUrl {
private final StickerPackId packId;
private final byte[] packKey;
/**
* @throws InvalidStickerPackLinkException If url cannot be parsed.
*/
public static StickerPackUrl fromUri(URI uri) throws InvalidStickerPackLinkException {
final var rawQuery = uri.getRawFragment();
if (isEmpty(rawQuery)) {
throw new RuntimeException("Invalid sticker pack uri");
}
var query = Utils.getQueryMap(rawQuery);
var packIdString = query.get("pack_id");
var packKeyString = query.get("pack_key");
if (isEmpty(packIdString) || isEmpty(packKeyString)) {
throw new InvalidStickerPackLinkException("Incomplete sticker pack uri");
}
StickerPackId packId;
try {
packId = StickerPackId.deserialize(Hex.fromStringCondensed(packIdString));
} catch (IOException e) {
throw new InvalidStickerPackLinkException("Invalid sticker pack", e);
}
final byte[] packKey;
try {
packKey = Hex.fromStringCondensed(packKeyString);
} catch (IOException e) {
throw new InvalidStickerPackLinkException("Invalid sticker pack uri", e);
}
return new StickerPackUrl(packId, packKey);
}
public StickerPackUrl(final StickerPackId packId, final byte[] packKey) {
this.packId = packId;
this.packKey = packKey;
}
public URI getUrl() {
try {
return new URI("https",
"signal.art",
"/addstickers/",
"pack_id="
+ URLEncoder.encode(Hex.toStringCondensed(packId.serialize()), StandardCharsets.UTF_8)
+ "&pack_key="
+ URLEncoder.encode(Hex.toStringCondensed(packKey), StandardCharsets.UTF_8));
} catch (URISyntaxException e) {
throw new AssertionError(e);
}
}
public StickerPackId getPackId() {
return packId;
}
public byte[] getPackKey() {
return packKey;
}
public final static class InvalidStickerPackLinkException extends Exception {
public InvalidStickerPackLinkException(String message) {
super(message);
}
public InvalidStickerPackLinkException(final String message, final Throwable cause) {
super(message, cause);
}
}
}

View file

@ -14,8 +14,12 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiFunction;
@ -106,4 +110,16 @@ public class Utils {
}
}, leftStream.isParallel() || rightStream.isParallel());
}
public static Map<String, String> getQueryMap(String query) {
var params = query.split("&");
var map = new HashMap<String, String>();
for (var param : params) {
final var paramParts = param.split("=");
var name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8);
var value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8);
map.put(name, value);
}
return map;
}
}