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