1 package org
.asamk
.signal
.manager
.util
;
3 import com
.fasterxml
.jackson
.databind
.ObjectMapper
;
5 import org
.asamk
.signal
.manager
.api
.Pair
;
6 import org
.asamk
.signal
.manager
.api
.StickerPackInvalidException
;
7 import org
.asamk
.signal
.manager
.storage
.stickerPacks
.JsonStickerPack
;
8 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceStickerManifestUpload
;
10 import java
.io
.BufferedInputStream
;
12 import java
.io
.FileInputStream
;
13 import java
.io
.IOException
;
14 import java
.io
.InputStream
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Optional
;
17 import java
.util
.zip
.ZipFile
;
19 public class StickerUtils
{
21 public static SignalServiceStickerManifestUpload
getSignalServiceStickerManifestUpload(
23 ) throws IOException
, StickerPackInvalidException
{
25 String rootPath
= null;
27 if (file
.getName().endsWith(".zip")) {
28 zip
= new ZipFile(file
);
29 } else if (file
.getName().equals("manifest.json")) {
30 rootPath
= file
.getParent();
32 throw new StickerPackInvalidException("Could not find manifest.json");
35 var pack
= parseStickerPack(rootPath
, zip
);
37 if (pack
.stickers() == null) {
38 throw new StickerPackInvalidException("Must set a 'stickers' field.");
41 if (pack
.stickers().isEmpty()) {
42 throw new StickerPackInvalidException("Must include stickers.");
45 var stickers
= new ArrayList
<SignalServiceStickerManifestUpload
.StickerInfo
>(pack
.stickers().size());
46 for (var sticker
: pack
.stickers()) {
47 if (sticker
.file() == null) {
48 throw new StickerPackInvalidException("Must set a 'file' field on each sticker.");
51 Pair
<InputStream
, Long
> data
;
53 data
= getInputStreamAndLength(rootPath
, zip
, sticker
.file());
54 } catch (IOException ignored
) {
55 throw new StickerPackInvalidException("Could not find find " + sticker
.file());
58 var contentType
= sticker
.contentType() != null && !sticker
.contentType().isEmpty()
59 ? sticker
.contentType()
60 : getContentType(rootPath
, zip
, sticker
.file());
61 var stickerInfo
= new SignalServiceStickerManifestUpload
.StickerInfo(data
.first(),
63 Optional
.ofNullable(sticker
.emoji()).orElse(""),
65 stickers
.add(stickerInfo
);
68 SignalServiceStickerManifestUpload
.StickerInfo cover
= null;
69 if (pack
.cover() != null) {
70 if (pack
.cover().file() == null) {
71 throw new StickerPackInvalidException("Must set a 'file' field on the cover.");
74 Pair
<InputStream
, Long
> data
;
76 data
= getInputStreamAndLength(rootPath
, zip
, pack
.cover().file());
77 } catch (IOException ignored
) {
78 throw new StickerPackInvalidException("Could not find find " + pack
.cover().file());
81 var contentType
= pack
.cover().contentType() != null && !pack
.cover().contentType().isEmpty() ? pack
.cover()
82 .contentType() : getContentType(rootPath
, zip
, pack
.cover().file());
83 cover
= new SignalServiceStickerManifestUpload
.StickerInfo(data
.first(),
85 Optional
.ofNullable(pack
.cover().emoji()).orElse(""),
89 return new SignalServiceStickerManifestUpload(pack
.title(), pack
.author(), cover
, stickers
);
92 private static JsonStickerPack
parseStickerPack(String rootPath
, ZipFile zip
) throws IOException
{
93 InputStream inputStream
;
95 inputStream
= zip
.getInputStream(zip
.getEntry("manifest.json"));
97 inputStream
= new FileInputStream((new File(rootPath
, "manifest.json")));
99 return new ObjectMapper().readValue(inputStream
, JsonStickerPack
.class);
102 private static Pair
<InputStream
, Long
> getInputStreamAndLength(
103 final String rootPath
,
106 ) throws IOException
{
108 final var entry
= zip
.getEntry(subfile
);
109 return new Pair
<>(zip
.getInputStream(entry
), entry
.getSize());
111 final var file
= new File(rootPath
, subfile
);
112 return new Pair
<>(new FileInputStream(file
), file
.length());
116 private static String
getContentType(
117 final String rootPath
,
120 ) throws IOException
{
122 final var entry
= zip
.getEntry(subfile
);
123 try (InputStream bufferedStream
= new BufferedInputStream(zip
.getInputStream(entry
))) {
124 return MimeUtils
.getStreamMimeType(bufferedStream
).orElse(null);
127 final var file
= new File(rootPath
, subfile
);
128 return MimeUtils
.getFileMimeType(file
).orElse(null);