From 0f66bb13b9f6fbf782ff604955af91bd3604c035 Mon Sep 17 00:00:00 2001 From: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:30:45 -0800 Subject: [PATCH] Improve compatibility for max long values in backups --- ts/services/backups/export.ts | 6 ++--- ts/services/backups/import.ts | 25 +++++++++++--------- ts/test-both/util/timestampLongUtils_test.ts | 25 ++++++++++++++++++++ ts/util/timestampLongUtils.ts | 10 ++++++++ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/ts/services/backups/export.ts b/ts/services/backups/export.ts index 44327aeb8b..88bcbe3c68 100644 --- a/ts/services/backups/export.ts +++ b/ts/services/backups/export.ts @@ -398,7 +398,7 @@ export class BackupExportStream extends Readable { name, restrictions: toCallLinkRestrictionsProto(restrictions), expirationMs: isNumber(expiration) - ? Long.fromNumber(expiration) + ? getSafeLongFromTimestamp(expiration) : null, }, }, @@ -848,7 +848,7 @@ export class BackupExportStream extends Readable { ? { notRegistered: { unregisteredTimestamp: convo.firstUnregisteredAt - ? Long.fromNumber(convo.firstUnregisteredAt) + ? getSafeLongFromTimestamp(convo.firstUnregisteredAt) : null, }, } @@ -1323,7 +1323,7 @@ export class BackupExportStream extends Readable { groupCall.state = toGroupCallStateProto(callHistory.status); groupCall.startedCallTimestamp = Long.fromNumber(callHistory.timestamp); if (callHistory.endedTimestamp != null) { - groupCall.endedCallTimestamp = Long.fromNumber( + groupCall.endedCallTimestamp = getSafeLongFromTimestamp( callHistory.endedTimestamp ); } diff --git a/ts/services/backups/import.ts b/ts/services/backups/import.ts index 1071687eec..a59b62f1b0 100644 --- a/ts/services/backups/import.ts +++ b/ts/services/backups/import.ts @@ -55,7 +55,10 @@ import type { QuotedMessageType, } from '../../model-types.d'; import { assertDev, strictAssert } from '../../util/assert'; -import { getTimestampFromLong } from '../../util/timestampLongUtils'; +import { + getTimestampFromLong, + getTimestampOrUndefinedFromLong, +} from '../../util/timestampLongUtils'; import { DurationInSeconds, SECOND } from '../../util/durations'; import { calculateExpirationTimestamp } from '../../util/expirationTimer'; import { dropNull } from '../../util/dropNull'; @@ -872,7 +875,9 @@ export class BackupImportStream extends Writable { } if (contact.notRegistered) { - const timestamp = contact.notRegistered.unregisteredTimestamp?.toNumber(); + const timestamp = getTimestampOrUndefinedFromLong( + contact.notRegistered.unregisteredTimestamp + ); attrs.discoveredUnregisteredAt = timestamp || this.now; attrs.firstUnregisteredAt = timestamp || undefined; } else { @@ -1216,10 +1221,9 @@ export class BackupImportStream extends Writable { ? DurationInSeconds.fromMillis(chat.expirationTimerMs.toNumber()) : undefined; conversation.expireTimerVersion = chat.expireTimerVersion || 1; - conversation.muteExpiresAt = - chat.muteUntilMs && !chat.muteUntilMs.isZero() - ? getTimestampFromLong(chat.muteUntilMs) - : undefined; + conversation.muteExpiresAt = getTimestampOrUndefinedFromLong( + chat.muteUntilMs + ); conversation.markedUnread = chat.markedUnread === true; conversation.dontNotifyForMentionsIfMuted = chat.dontNotifyForMentionsIfMuted === true; @@ -1298,10 +1302,9 @@ export class BackupImportStream extends Writable { chatConvo.unreadCount = (chatConvo.unreadCount ?? 0) + 1; } - const expirationStartTimestamp = - item.expireStartDate && !item.expireStartDate.isZero() - ? getTimestampFromLong(item.expireStartDate) - : undefined; + const expirationStartTimestamp = getTimestampOrUndefinedFromLong( + item.expireStartDate + ); const expireTimer = item.expiresInMs && !item.expiresInMs.isZero() ? DurationInSeconds.fromMillis(item.expiresInMs.toNumber()) @@ -2198,7 +2201,7 @@ export class BackupImportStream extends Writable { peerId: groupId, direction: isRingerMe ? CallDirection.Outgoing : CallDirection.Incoming, timestamp: startedCallTimestamp.toNumber(), - endedTimestamp: endedCallTimestamp?.toNumber() || null, + endedTimestamp: getTimestampFromLong(endedCallTimestamp) || null, }; await this.saveCallHistory(callHistory); diff --git a/ts/test-both/util/timestampLongUtils_test.ts b/ts/test-both/util/timestampLongUtils_test.ts index 435d8b1680..ab1d36e625 100644 --- a/ts/test-both/util/timestampLongUtils_test.ts +++ b/ts/test-both/util/timestampLongUtils_test.ts @@ -7,6 +7,7 @@ import Long from 'long'; import { getSafeLongFromTimestamp, getTimestampFromLong, + getTimestampOrUndefinedFromLong, } from '../../util/timestampLongUtils'; describe('getSafeLongFromTimestamp', () => { @@ -46,3 +47,27 @@ describe('getTimestampFromLong', () => { assert.equal(getTimestampFromLong(null), 0); }); }); + +describe('getTimestampOrUndefinedFromLong', () => { + it('returns undefined when passed 0 Long', () => { + assert.equal( + getTimestampOrUndefinedFromLong(Long.fromNumber(0)), + undefined + ); + }); + + it('returns Number.MAX_SAFE_INTEGER when passed Long.MAX_VALUE', () => { + assert.equal( + getTimestampOrUndefinedFromLong(Long.MAX_VALUE), + Number.MAX_SAFE_INTEGER + ); + }); + + it('returns a normal number', () => { + assert.equal(getTimestampOrUndefinedFromLong(Long.fromNumber(16)), 16); + }); + + it('returns undefined for null value', () => { + assert.equal(getTimestampOrUndefinedFromLong(null), undefined); + }); +}); diff --git a/ts/util/timestampLongUtils.ts b/ts/util/timestampLongUtils.ts index 7cd3484515..2af5ba15bd 100644 --- a/ts/util/timestampLongUtils.ts +++ b/ts/util/timestampLongUtils.ts @@ -24,3 +24,13 @@ export function getTimestampFromLong(value?: Long | null): number { return num; } + +export function getTimestampOrUndefinedFromLong( + value?: Long | null +): number | undefined { + if (!value || value.isZero()) { + return undefined; + } + + return getTimestampFromLong(value); +}