]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/stickers/StickerStore.java
aacd18bd57ba9270e3c508f5d6afce27efd7744e
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / stickers / StickerStore.java
1 package org.asamk.signal.manager.storage.stickers;
2
3 import org.asamk.signal.manager.api.StickerPackId;
4 import org.asamk.signal.manager.storage.Database;
5 import org.asamk.signal.manager.storage.Utils;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 import java.sql.Connection;
10 import java.sql.ResultSet;
11 import java.sql.SQLException;
12 import java.util.Collection;
13 import java.util.List;
14
15 public class StickerStore {
16
17 private final static Logger logger = LoggerFactory.getLogger(StickerStore.class);
18 private static final String TABLE_STICKER = "sticker";
19
20 private final Database database;
21
22 public static void createSql(Connection connection) throws SQLException {
23 // When modifying the CREATE statement here, also add a migration in AccountDatabase.java
24 try (final var statement = connection.createStatement()) {
25 statement.executeUpdate("""
26 CREATE TABLE sticker (
27 _id INTEGER PRIMARY KEY,
28 pack_id BLOB UNIQUE NOT NULL,
29 pack_key BLOB NOT NULL,
30 installed INTEGER NOT NULL DEFAULT FALSE
31 ) STRICT;
32 """);
33 }
34 }
35
36 public StickerStore(final Database database) {
37 this.database = database;
38 }
39
40 public List<StickerPack> getStickerPacks() {
41 final var sql = (
42 """
43 SELECT s._id, s.pack_id, s.pack_key, s.installed
44 FROM %s s
45 """
46 ).formatted(TABLE_STICKER);
47 try (final var connection = database.getConnection()) {
48 try (final var statement = connection.prepareStatement(sql)) {
49 try (var result = Utils.executeQueryForStream(statement, this::getStickerPackFromResultSet)) {
50 return result.toList();
51 }
52 }
53 } catch (SQLException e) {
54 throw new RuntimeException("Failed read from sticker store", e);
55 }
56 }
57
58 public StickerPack getStickerPack(StickerPackId packId) {
59 final var sql = (
60 """
61 SELECT s._id, s.pack_id, s.pack_key, s.installed
62 FROM %s s
63 WHERE s.pack_id = ?
64 """
65 ).formatted(TABLE_STICKER);
66 try (final var connection = database.getConnection()) {
67 try (final var statement = connection.prepareStatement(sql)) {
68 statement.setBytes(1, packId.serialize());
69 return Utils.executeQueryForOptional(statement, this::getStickerPackFromResultSet).orElse(null);
70 }
71 } catch (SQLException e) {
72 throw new RuntimeException("Failed read from sticker store", e);
73 }
74 }
75
76 public void addStickerPack(StickerPack stickerPack) {
77 final var sql = (
78 """
79 INSERT INTO %s (pack_id, pack_key, installed)
80 VALUES (?, ?, ?)
81 """
82 ).formatted(TABLE_STICKER);
83 try (final var connection = database.getConnection()) {
84 try (final var statement = connection.prepareStatement(sql)) {
85 statement.setBytes(1, stickerPack.packId().serialize());
86 statement.setBytes(2, stickerPack.packKey());
87 statement.setBoolean(3, stickerPack.isInstalled());
88 statement.executeUpdate();
89 }
90 } catch (SQLException e) {
91 throw new RuntimeException("Failed update sticker store", e);
92 }
93 }
94
95 public void updateStickerPackInstalled(StickerPackId stickerPackId, boolean installed) {
96 final var sql = (
97 """
98 UPDATE %s
99 SET installed = ?
100 WHERE pack_id = ?
101 """
102 ).formatted(TABLE_STICKER);
103 try (final var connection = database.getConnection()) {
104 try (final var statement = connection.prepareStatement(sql)) {
105 statement.setBytes(1, stickerPackId.serialize());
106 statement.setBoolean(2, installed);
107 statement.executeUpdate();
108 }
109 } catch (SQLException e) {
110 throw new RuntimeException("Failed update sticker store", e);
111 }
112 }
113
114 void addLegacyStickers(Collection<StickerPack> stickerPacks) {
115 logger.debug("Migrating legacy stickers to database");
116 long start = System.nanoTime();
117 final var sql = (
118 """
119 INSERT INTO %s (pack_id, pack_key, installed)
120 VALUES (?, ?, ?)
121 """
122 ).formatted(TABLE_STICKER);
123 try (final var connection = database.getConnection()) {
124 connection.setAutoCommit(false);
125 try (final var statement = connection.prepareStatement("DELETE FROM %s".formatted(TABLE_STICKER))) {
126 statement.executeUpdate();
127 }
128 try (final var statement = connection.prepareStatement(sql)) {
129 for (final var sticker : stickerPacks) {
130 statement.setBytes(1, sticker.packId().serialize());
131 statement.setBytes(2, sticker.packKey());
132 statement.setBoolean(3, sticker.isInstalled());
133 statement.executeUpdate();
134 }
135 }
136 connection.commit();
137 } catch (SQLException e) {
138 throw new RuntimeException("Failed update sticker store", e);
139 }
140 logger.debug("Stickers migration took {}ms", (System.nanoTime() - start) / 1000000);
141 }
142
143 private StickerPack getStickerPackFromResultSet(ResultSet resultSet) throws SQLException {
144 final var internalId = resultSet.getLong("_id");
145 final var packId = resultSet.getBytes("pack_id");
146 final var packKey = resultSet.getBytes("pack_key");
147 final var installed = resultSet.getBoolean("installed");
148 return new StickerPack(internalId, StickerPackId.deserialize(packId), packKey, installed);
149 }
150 }