mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
parent
5171107a29
commit
5a4f4ba6db
11 changed files with 91 additions and 31 deletions
|
@ -11,6 +11,7 @@ public record Contact(
|
|||
String note,
|
||||
String color,
|
||||
int messageExpirationTime,
|
||||
int messageExpirationTimeVersion,
|
||||
long muteUntil,
|
||||
boolean hideStory,
|
||||
boolean isBlocked,
|
||||
|
@ -29,6 +30,7 @@ public record Contact(
|
|||
builder.note,
|
||||
builder.color,
|
||||
builder.messageExpirationTime,
|
||||
builder.messageExpirationTimeVersion,
|
||||
builder.muteUntil,
|
||||
builder.hideStory,
|
||||
builder.isBlocked,
|
||||
|
@ -84,6 +86,7 @@ public record Contact(
|
|||
private String note;
|
||||
private String color;
|
||||
private int messageExpirationTime;
|
||||
private int messageExpirationTimeVersion = 1;
|
||||
private long muteUntil;
|
||||
private boolean hideStory;
|
||||
private boolean isBlocked;
|
||||
|
@ -139,6 +142,11 @@ public record Contact(
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder withMessageExpirationTimeVersion(final int val) {
|
||||
messageExpirationTimeVersion = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withMuteUntil(final long val) {
|
||||
muteUntil = val;
|
||||
return this;
|
||||
|
|
|
@ -29,8 +29,7 @@ public class ServiceConfig {
|
|||
|
||||
public static AccountAttributes.Capabilities getCapabilities(boolean isPrimaryDevice) {
|
||||
final var deleteSync = !isPrimaryDevice;
|
||||
final var versionedExpirationTimer = !isPrimaryDevice;
|
||||
return new AccountAttributes.Capabilities(true, deleteSync, versionedExpirationTimer);
|
||||
return new AccountAttributes.Capabilities(true, deleteSync, true);
|
||||
}
|
||||
|
||||
public static ServiceEnvironmentConfig getServiceEnvironmentConfig(
|
||||
|
|
|
@ -36,8 +36,34 @@ public class ContactHelper {
|
|||
return;
|
||||
}
|
||||
final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
|
||||
final var version = contact == null
|
||||
? 1
|
||||
: contact.messageExpirationTimeVersion() == Integer.MAX_VALUE
|
||||
? Integer.MAX_VALUE
|
||||
: contact.messageExpirationTimeVersion() + 1;
|
||||
account.getContactStore()
|
||||
.storeContact(recipientId, builder.withMessageExpirationTime(messageExpirationTimer).build());
|
||||
.storeContact(recipientId,
|
||||
builder.withMessageExpirationTime(messageExpirationTimer)
|
||||
.withMessageExpirationTimeVersion(version)
|
||||
.build());
|
||||
}
|
||||
|
||||
public void setExpirationTimer(
|
||||
RecipientId recipientId, int messageExpirationTimer, int messageExpirationTimerVersion
|
||||
) {
|
||||
var contact = account.getContactStore().getContact(recipientId);
|
||||
if (contact != null && (
|
||||
contact.messageExpirationTime() == messageExpirationTimer
|
||||
|| contact.messageExpirationTimeVersion() >= messageExpirationTimerVersion
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
|
||||
account.getContactStore()
|
||||
.storeContact(recipientId,
|
||||
builder.withMessageExpirationTime(messageExpirationTimer)
|
||||
.withMessageExpirationTimeVersion(messageExpirationTimerVersion)
|
||||
.build());
|
||||
}
|
||||
|
||||
public void setContactBlocked(RecipientId recipientId, boolean blocked) {
|
||||
|
|
|
@ -802,7 +802,9 @@ public final class IncomingMessageHandler {
|
|||
}
|
||||
} else if (conversationPartnerAddress != null) {
|
||||
context.getContactHelper()
|
||||
.setExpirationTimer(conversationPartnerAddress.recipientId(), message.getExpiresInSeconds());
|
||||
.setExpirationTimer(conversationPartnerAddress.recipientId(),
|
||||
message.getExpiresInSeconds(),
|
||||
message.getExpireTimerVersion());
|
||||
}
|
||||
}
|
||||
if (!ignoreAttachments) {
|
||||
|
|
|
@ -86,8 +86,8 @@ public class SendHelper {
|
|||
account.getContactStore().storeContact(recipientId, contact);
|
||||
}
|
||||
|
||||
final var expirationTime = contact.messageExpirationTime();
|
||||
messageBuilder.withExpiration(expirationTime);
|
||||
messageBuilder.withExpiration(contact.messageExpirationTime());
|
||||
messageBuilder.withExpireTimerVersion(contact.messageExpirationTimeVersion());
|
||||
|
||||
if (!contact.isBlocked()) {
|
||||
final var profileKey = account.getProfileKey().serialize();
|
||||
|
@ -187,8 +187,8 @@ public class SendHelper {
|
|||
) {
|
||||
final var recipientId = account.getSelfRecipientId();
|
||||
final var contact = account.getContactStore().getContact(recipientId);
|
||||
final var expirationTime = contact != null ? contact.messageExpirationTime() : 0;
|
||||
messageBuilder.withExpiration(expirationTime);
|
||||
messageBuilder.withExpiration(contact != null ? contact.messageExpirationTime() : 0);
|
||||
messageBuilder.withExpireTimerVersion(contact != null ? contact.messageExpirationTimeVersion() : 1);
|
||||
|
||||
var message = messageBuilder.build();
|
||||
return sendSelfMessage(message, editTargetTimestamp);
|
||||
|
|
|
@ -239,7 +239,7 @@ public class SyncHelper {
|
|||
Optional.ofNullable(verifiedMessage),
|
||||
Optional.ofNullable(profileKey),
|
||||
Optional.ofNullable(contact == null ? null : contact.messageExpirationTime()),
|
||||
Optional.empty(),
|
||||
Optional.ofNullable(contact == null ? null : contact.messageExpirationTimeVersion()),
|
||||
Optional.empty(),
|
||||
contact != null && contact.isArchived());
|
||||
}
|
||||
|
@ -392,7 +392,18 @@ public class SyncHelper {
|
|||
TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
|
||||
}
|
||||
if (c.getExpirationTimer().isPresent()) {
|
||||
builder.withMessageExpirationTime(c.getExpirationTimer().get());
|
||||
if (c.getExpirationTimerVersion().isPresent() && (
|
||||
contact == null || c.getExpirationTimerVersion().get() > contact.messageExpirationTimeVersion()
|
||||
)) {
|
||||
builder.withMessageExpirationTime(c.getExpirationTimer().get());
|
||||
builder.withMessageExpirationTimeVersion(c.getExpirationTimerVersion().get());
|
||||
} else {
|
||||
logger.debug(
|
||||
"[ContactSync] {} was synced with an old expiration timer. Ignoring. Received: {} Current: ${}",
|
||||
recipientId,
|
||||
c.getExpirationTimerVersion(),
|
||||
contact == null ? 1 : contact.messageExpirationTimeVersion());
|
||||
}
|
||||
}
|
||||
builder.withIsArchived(c.isArchived());
|
||||
account.getContactStore().storeContact(recipientId, builder.build());
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
public class AccountDatabase extends Database {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AccountDatabase.class);
|
||||
private static final long DATABASE_VERSION = 26;
|
||||
private static final long DATABASE_VERSION = 27;
|
||||
|
||||
private AccountDatabase(final HikariDataSource dataSource) {
|
||||
super(logger, DATABASE_VERSION, dataSource);
|
||||
|
@ -600,6 +600,14 @@ public class AccountDatabase extends Database {
|
|||
""");
|
||||
}
|
||||
}
|
||||
if (oldVersion < 27) {
|
||||
logger.debug("Updating database: Create expiration_time_version column");
|
||||
try (final var statement = connection.createStatement()) {
|
||||
statement.executeUpdate("""
|
||||
ALTER TABLE recipient ADD expiration_time_version INTEGER DEFAULT 1 NOT NULL;
|
||||
""");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void createUuidMappingTable(
|
||||
|
|
|
@ -864,6 +864,7 @@ public class SignalAccount implements Closeable {
|
|||
null,
|
||||
contact.color,
|
||||
contact.messageExpirationTime,
|
||||
1,
|
||||
0,
|
||||
false,
|
||||
contact.blocked,
|
||||
|
@ -939,6 +940,7 @@ public class SignalAccount implements Closeable {
|
|||
getContactStore().storeContact(recipientId,
|
||||
Contact.newBuilder(contact)
|
||||
.withMessageExpirationTime(thread.messageExpirationTime)
|
||||
.withMessageExpirationTimeVersion(1)
|
||||
.build());
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -46,6 +46,7 @@ public class LegacyRecipientStore2 {
|
|||
null,
|
||||
r.contact.color,
|
||||
r.contact.messageExpirationTime,
|
||||
1,
|
||||
0,
|
||||
false,
|
||||
r.contact.blocked,
|
||||
|
|
|
@ -79,6 +79,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
color TEXT,
|
||||
|
||||
expiration_time INTEGER NOT NULL DEFAULT 0,
|
||||
expiration_time_version INTEGER DEFAULT 1 NOT NULL,
|
||||
mute_until INTEGER NOT NULL DEFAULT 0,
|
||||
blocked INTEGER NOT NULL DEFAULT FALSE,
|
||||
archived INTEGER NOT NULL DEFAULT FALSE,
|
||||
|
@ -332,7 +333,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
public List<Pair<RecipientId, Contact>> getContacts() {
|
||||
final var sql = (
|
||||
"""
|
||||
SELECT r._id, r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
|
||||
SELECT r._id, r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.expiration_time_version, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
|
||||
FROM %s r
|
||||
WHERE (r.number IS NOT NULL OR r.aci IS NOT NULL) AND %s AND r.hidden = FALSE
|
||||
"""
|
||||
|
@ -356,7 +357,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
SELECT r._id,
|
||||
r.number, r.aci, r.pni, r.username,
|
||||
r.profile_key, r.profile_key_credential,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.expiration_time_version, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities, r.profile_phone_number_sharing,
|
||||
r.discoverable,
|
||||
r.storage_record
|
||||
|
@ -376,7 +377,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
SELECT r._id,
|
||||
r.number, r.aci, r.pni, r.username,
|
||||
r.profile_key, r.profile_key_credential,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.expiration_time_version, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities, r.profile_phone_number_sharing,
|
||||
r.discoverable,
|
||||
r.storage_record
|
||||
|
@ -413,7 +414,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
SELECT r._id,
|
||||
r.number, r.aci, r.pni, r.username,
|
||||
r.profile_key, r.profile_key_credential,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.expiration_time_version, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
|
||||
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities, r.profile_phone_number_sharing,
|
||||
r.discoverable,
|
||||
r.storage_record
|
||||
|
@ -817,7 +818,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
final var sql = (
|
||||
"""
|
||||
UPDATE %s
|
||||
SET given_name = ?, family_name = ?, nick_name = ?, expiration_time = ?, mute_until = ?, hide_story = ?, profile_sharing = ?, color = ?, blocked = ?, archived = ?, unregistered_timestamp = ?, nick_name_given_name = ?, nick_name_family_name = ?, note = ?
|
||||
SET given_name = ?, family_name = ?, nick_name = ?, expiration_time = ?, expiration_time_version = ?, mute_until = ?, hide_story = ?, profile_sharing = ?, color = ?, blocked = ?, archived = ?, unregistered_timestamp = ?, nick_name_given_name = ?, nick_name_family_name = ?, note = ?
|
||||
WHERE _id = ?
|
||||
"""
|
||||
).formatted(TABLE_RECIPIENT);
|
||||
|
@ -826,21 +827,22 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
statement.setString(2, contact == null ? null : contact.familyName());
|
||||
statement.setString(3, contact == null ? null : contact.nickName());
|
||||
statement.setInt(4, contact == null ? 0 : contact.messageExpirationTime());
|
||||
statement.setLong(5, contact == null ? 0 : contact.muteUntil());
|
||||
statement.setBoolean(6, contact != null && contact.hideStory());
|
||||
statement.setBoolean(7, contact != null && contact.isProfileSharingEnabled());
|
||||
statement.setString(8, contact == null ? null : contact.color());
|
||||
statement.setBoolean(9, contact != null && contact.isBlocked());
|
||||
statement.setBoolean(10, contact != null && contact.isArchived());
|
||||
statement.setInt(5, contact == null ? 0 : Math.max(1, contact.messageExpirationTimeVersion()));
|
||||
statement.setLong(6, contact == null ? 0 : contact.muteUntil());
|
||||
statement.setBoolean(7, contact != null && contact.hideStory());
|
||||
statement.setBoolean(8, contact != null && contact.isProfileSharingEnabled());
|
||||
statement.setString(9, contact == null ? null : contact.color());
|
||||
statement.setBoolean(10, contact != null && contact.isBlocked());
|
||||
statement.setBoolean(11, contact != null && contact.isArchived());
|
||||
if (contact == null || contact.unregisteredTimestamp() == null) {
|
||||
statement.setNull(11, Types.INTEGER);
|
||||
statement.setNull(12, Types.INTEGER);
|
||||
} else {
|
||||
statement.setLong(11, contact.unregisteredTimestamp());
|
||||
statement.setLong(12, contact.unregisteredTimestamp());
|
||||
}
|
||||
statement.setString(12, contact == null ? null : contact.nickNameGivenName());
|
||||
statement.setString(13, contact == null ? null : contact.nickNameFamilyName());
|
||||
statement.setString(14, contact == null ? null : contact.note());
|
||||
statement.setLong(15, recipientId.id());
|
||||
statement.setString(13, contact == null ? null : contact.nickNameGivenName());
|
||||
statement.setString(14, contact == null ? null : contact.nickNameFamilyName());
|
||||
statement.setString(15, contact == null ? null : contact.note());
|
||||
statement.setLong(16, recipientId.id());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
if (contact != null && contact.unregisteredTimestamp() != null) {
|
||||
|
@ -918,8 +920,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
markDiscoverable(connection, recipientId, false);
|
||||
final var contact = getContact(connection, recipientId);
|
||||
if (recipientAddress.get().address().aci().isEmpty() || (
|
||||
contact != null
|
||||
&& contact.unregisteredTimestamp() != null
|
||||
contact != null && contact.unregisteredTimestamp() != null
|
||||
)) {
|
||||
markUnregisteredAndSplitIfNecessary(connection, recipientId);
|
||||
}
|
||||
|
@ -1416,7 +1417,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
private Contact getContact(final Connection connection, final RecipientId recipientId) throws SQLException {
|
||||
final var sql = (
|
||||
"""
|
||||
SELECT r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
|
||||
SELECT r.given_name, r.family_name, r.nick_name, r.nick_name_given_name, r.nick_name_family_name, r.note, r.expiration_time, r.expiration_time_version, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
|
||||
FROM %s r
|
||||
WHERE r._id = ? AND (%s)
|
||||
"""
|
||||
|
@ -1514,6 +1515,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
|
|||
resultSet.getString("note"),
|
||||
resultSet.getString("color"),
|
||||
resultSet.getInt("expiration_time"),
|
||||
resultSet.getInt("expiration_time_version"),
|
||||
resultSet.getLong("mute_until"),
|
||||
resultSet.getBoolean("hide_story"),
|
||||
resultSet.getBoolean("blocked"),
|
||||
|
|
|
@ -699,6 +699,7 @@ public class DbusManagerImpl implements Manager {
|
|||
null,
|
||||
null,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
false,
|
||||
contactBlocked,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue