1 package org
.asamk
.signal
.manager
.util
;
3 import com
.fasterxml
.jackson
.databind
.ObjectMapper
;
5 import org
.asamk
.signal
.manager
.JsonStickerPack
;
6 import org
.asamk
.signal
.manager
.StickerPackInvalidException
;
7 import org
.whispersystems
.libsignal
.util
.Pair
;
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()
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()
83 ? pack
.cover
.contentType
84 : getContentType(rootPath
, zip
, pack
.cover
.file
);
85 cover
= new SignalServiceStickerManifestUpload
.StickerInfo(data
.first(),
87 Optional
.fromNullable(pack
.cover
.emoji
).or(""),
91 return new SignalServiceStickerManifestUpload(pack
.title
, pack
.author
, cover
, stickers
);
94 private static JsonStickerPack
parseStickerPack(String rootPath
, ZipFile zip
) throws IOException
{
95 InputStream inputStream
;
97 inputStream
= zip
.getInputStream(zip
.getEntry("manifest.json"));
99 inputStream
= new FileInputStream((new File(rootPath
, "manifest.json")));
101 return new ObjectMapper().readValue(inputStream
, JsonStickerPack
.class);
104 private static Pair
<InputStream
, Long
> getInputStreamAndLength(
105 final String rootPath
, final ZipFile zip
, final String subfile
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
, final ZipFile zip
, final String subfile
118 ) throws IOException
{
120 final var entry
= zip
.getEntry(subfile
);
121 try (InputStream bufferedStream
= new BufferedInputStream(zip
.getInputStream(entry
))) {
122 return URLConnection
.guessContentTypeFromStream(bufferedStream
);
125 final var file
= new File(rootPath
, subfile
);
126 return Utils
.getFileMimeType(file
, null);