1 package org
.asamk
.signal
.manager
.util
;
3 import com
.fasterxml
.jackson
.databind
.ObjectMapper
;
5 import org
.asamk
.signal
.manager
.api
.StickerPackInvalidException
;
6 import org
.asamk
.signal
.manager
.api
.Pair
;
7 import org
.asamk
.signal
.manager
.storage
.stickerPacks
.JsonStickerPack
;
8 import org
.whispersystems
.libsignal
.util
.guava
.Optional
;
9 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceStickerManifestUpload
;
11 import java
.io
.BufferedInputStream
;
13 import java
.io
.FileInputStream
;
14 import java
.io
.IOException
;
15 import java
.io
.InputStream
;
16 import java
.net
.URLConnection
;
17 import java
.util
.ArrayList
;
18 import java
.util
.zip
.ZipFile
;
20 public class StickerUtils
{
22 public static SignalServiceStickerManifestUpload
getSignalServiceStickerManifestUpload(
24 ) throws IOException
, StickerPackInvalidException
{
26 String rootPath
= null;
28 if (file
.getName().endsWith(".zip")) {
29 zip
= new ZipFile(file
);
30 } else if (file
.getName().equals("manifest.json")) {
31 rootPath
= file
.getParent();
33 throw new StickerPackInvalidException("Could not find manifest.json");
36 var pack
= parseStickerPack(rootPath
, zip
);
38 if (pack
.stickers() == null) {
39 throw new StickerPackInvalidException("Must set a 'stickers' field.");
42 if (pack
.stickers().isEmpty()) {
43 throw new StickerPackInvalidException("Must include stickers.");
46 var stickers
= new ArrayList
<SignalServiceStickerManifestUpload
.StickerInfo
>(pack
.stickers().size());
47 for (var sticker
: pack
.stickers()) {
48 if (sticker
.file() == null) {
49 throw new StickerPackInvalidException("Must set a 'file' field on each sticker.");
52 Pair
<InputStream
, Long
> data
;
54 data
= getInputStreamAndLength(rootPath
, zip
, sticker
.file());
55 } catch (IOException ignored
) {
56 throw new StickerPackInvalidException("Could not find find " + sticker
.file());
59 var contentType
= sticker
.contentType() != null && !sticker
.contentType().isEmpty()
60 ? sticker
.contentType()
61 : getContentType(rootPath
, zip
, sticker
.file());
62 var stickerInfo
= new SignalServiceStickerManifestUpload
.StickerInfo(data
.first(),
64 Optional
.fromNullable(sticker
.emoji()).or(""),
66 stickers
.add(stickerInfo
);
69 SignalServiceStickerManifestUpload
.StickerInfo cover
= null;
70 if (pack
.cover() != null) {
71 if (pack
.cover().file() == null) {
72 throw new StickerPackInvalidException("Must set a 'file' field on the cover.");
75 Pair
<InputStream
, Long
> data
;
77 data
= getInputStreamAndLength(rootPath
, zip
, pack
.cover().file());
78 } catch (IOException ignored
) {
79 throw new StickerPackInvalidException("Could not find find " + pack
.cover().file());
82 var contentType
= pack
.cover().contentType() != null && !pack
.cover().contentType().isEmpty() ? pack
.cover()
83 .contentType() : getContentType(rootPath
, zip
, pack
.cover().file());
84 cover
= new SignalServiceStickerManifestUpload
.StickerInfo(data
.first(),
86 Optional
.fromNullable(pack
.cover().emoji()).or(""),
90 return new SignalServiceStickerManifestUpload(pack
.title(), pack
.author(), cover
, stickers
);
93 private static JsonStickerPack
parseStickerPack(String rootPath
, ZipFile zip
) throws IOException
{
94 InputStream inputStream
;
96 inputStream
= zip
.getInputStream(zip
.getEntry("manifest.json"));
98 inputStream
= new FileInputStream((new File(rootPath
, "manifest.json")));
100 return new ObjectMapper().readValue(inputStream
, JsonStickerPack
.class);
103 private static Pair
<InputStream
, Long
> getInputStreamAndLength(
104 final String rootPath
, final ZipFile zip
, final String subfile
105 ) throws IOException
{
107 final var entry
= zip
.getEntry(subfile
);
108 return new Pair
<>(zip
.getInputStream(entry
), entry
.getSize());
110 final var file
= new File(rootPath
, subfile
);
111 return new Pair
<>(new FileInputStream(file
), file
.length());
115 private static String
getContentType(
116 final String rootPath
, final ZipFile zip
, final String subfile
117 ) throws IOException
{
119 final var entry
= zip
.getEntry(subfile
);
120 try (InputStream bufferedStream
= new BufferedInputStream(zip
.getInputStream(entry
))) {
121 return URLConnection
.guessContentTypeFromStream(bufferedStream
);
124 final var file
= new File(rootPath
, subfile
);
125 return Utils
.getFileMimeType(file
, null);