Replace Wire with Swift-Protobuf for Backups

This commit is contained in:
Sasha Weiss
2024-07-29 15:26:01 -07:00
committed by GitHub
parent a817a93be6
commit d87164a073
49 changed files with 15885 additions and 15912 deletions

View File

@@ -47,7 +47,6 @@ pod 'libwebp', podspec: './ThirdParty/libwebp.podspec.json'
# third party pods
####
pod 'Wire'
pod 'Reachability', :inhibit_warnings => true
def ui_pods

View File

@@ -40,7 +40,6 @@ PODS:
- SQLCipher/common
- SSZipArchive (2.5.2)
- SwiftProtobuf (1.26.0)
- Wire (4.9.4)
- YYImage (1.0.4):
- YYImage/Core (= 1.0.4)
- YYImage/Core (1.0.4)
@@ -67,7 +66,6 @@ DEPENDENCIES:
- SQLCipher (from `https://github.com/signalapp/sqlcipher.git`, tag `v4.6.0-f_barrierfsync`)
- SSZipArchive (from `ThirdParty/SSZipArchive.podspec`)
- SwiftProtobuf (>= 1.14.0)
- Wire
- YYImage (from `https://github.com/signalapp/YYImage`)
- YYImage/libwebp (from `https://github.com/signalapp/YYImage`)
@@ -81,7 +79,6 @@ SPEC REPOS:
- PureLayout
- Reachability
- SwiftProtobuf
- Wire
EXTERNAL SOURCES:
blurhash:
@@ -164,9 +161,8 @@ SPEC CHECKSUMS:
SQLCipher: 30a8e81afa6128e600b17ffa77d0f92fa05ed208
SSZipArchive: 8c3485528a87fa6f90afdbfc33682eb61d985ae5
SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3
Wire: f5fe13fcad476bfd248f23a45a2004167c0ebae2
YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331
PODFILE CHECKSUM: 1cb467dcd01717f6a5002669fd1ddda483686dc9
PODFILE CHECKSUM: c8e79c1306b6cc192435ee4f514f6e9702e4ca10
COCOAPODS: 1.15.2

2
Pods

Submodule Pods updated: 57050a96b2...04f42f2c37

View File

@@ -1,65 +0,0 @@
#!/usr/bin/env bash
REPO_ROOT=$(git rev-parse --show-toplevel)
WIRE_COMPILER_VERSION="4.9.4"
WIRE_COMPILER_CHECKSUM="4134b15e77fa0725ac499d8aded607a1c5b34e7cd9581b18385d868ffb0bfcdd"
WIRE_COMPILER_JAR="$REPO_ROOT/Scripts/protos/WireCompiler-$WIRE_COMPILER_VERSION.jar"
# ------ #
if ! command -v sha256sum > /dev/null; then
echo "Error: missing sha256sum!"
exit 1
fi
if ! command -v java > /dev/null; then
echo "Error: Java must be installed!"
exit 1
fi
# ------ #
if ! [[ -f "$WIRE_COMPILER_JAR" ]]; then
echo "Downloading Wire compiler..."
REMOTE_JAR_URL="https://repo.maven.apache.org/maven2/com/squareup/wire/wire-compiler/$WIRE_COMPILER_VERSION/wire-compiler-$WIRE_COMPILER_VERSION-jar-with-dependencies.jar"
curl "$REMOTE_JAR_URL" --output "$WIRE_COMPILER_JAR"
fi
# ------ #
echo "Checking Wire compiler checksum..."
echo "$WIRE_COMPILER_CHECKSUM" "$WIRE_COMPILER_JAR" | sha256sum --check > /dev/null
if [ "$?" -ne 0 ]; then
echo "Error: JAR file checksum failed to validate!"
exit 1
fi
# ------ #
echo "Running Wire compiler..."
BACKUP_PROTOS_DIR="$REPO_ROOT/SignalServiceKit/protobuf/Backups"
java \
-jar "$WIRE_COMPILER_JAR" \
--proto_path="$BACKUP_PROTOS_DIR" \
--swift_out="$BACKUP_PROTOS_DIR" \
> /dev/null
if [ "$?" -ne 0 ]; then
echo "Error: failed to compile protos!"
exit 1
fi
# ------ #
echo "Adding license header to generated files..."
BACKUP_PROTO_FILES=$(find "$BACKUP_PROTOS_DIR" -name "*.swift")
"$REPO_ROOT"/Scripts/lint/lint-license-headers --fix $BACKUP_PROTO_FILES

View File

@@ -1775,7 +1775,6 @@
D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A0E7169DFFC500537ABF /* AVFoundation.framework */; };
D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D24B5BD4169F568C00681372 /* AudioToolbox.framework */; };
D2AEACDC16C426DA00C364C0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; };
D90D4D7C2BBB45880097C573 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = D90D4D6D2BBB45870097C573 /* README.md */; };
D90D4D842BBB61680097C573 /* MessageBackupEmptyFrameId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90D4D832BBB61680097C573 /* MessageBackupEmptyFrameId.swift */; };
D9106DFF2AC1FEFD007ABFE6 /* EmptyForCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9106DFE2AC1FEFD007ABFE6 /* EmptyForCodable.swift */; };
D9106E022AC20066007ABFE6 /* EmptyForCodableTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9106E002AC20061007ABFE6 /* EmptyForCodableTest.swift */; };
@@ -1857,12 +1856,14 @@
D962346B2C0E937500DAF6CB /* InterleavingCompositeCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D931080A2B338CE5006A034E /* InterleavingCompositeCursor.swift */; };
D962346D2C0E957800DAF6CB /* DeleteForMeMostRecentAddressableMessageCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D962346C2C0E957800DAF6CB /* DeleteForMeMostRecentAddressableMessageCursor.swift */; };
D96234702C0E99DE00DAF6CB /* DeleteForMeMostRecentAddressableMessageCursorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D962346F2C0E99DE00DAF6CB /* DeleteForMeMostRecentAddressableMessageCursorTest.swift */; };
D96269D92C58407400152314 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = D96269D82C58407400152314 /* README.md */; };
D968F71B2C3355AB00AB318B /* simple-chat-update-message.binproto in Resources */ = {isa = PBXBuildFile; fileRef = D968F7192C3355AA00AB318B /* simple-chat-update-message.binproto */; };
D968F71C2C3355AB00AB318B /* simple-chat-update-message.jsonproto in Resources */ = {isa = PBXBuildFile; fileRef = D968F71A2C3355AB00AB318B /* simple-chat-update-message.jsonproto */; };
D968F71E2C34884B00AB318B /* MessageBackupReleaseNotesRecipientArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D968F71D2C34884B00AB318B /* MessageBackupReleaseNotesRecipientArchiver.swift */; };
D96A94A72954E57F004EA434 /* DonateViewController+MonthlyPaypalDonation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D96A94A62954E57F004EA434 /* DonateViewController+MonthlyPaypalDonation.swift */; };
D96BE42E292EF04200E4FE1A /* PaypalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D96BE42D292EF04200E4FE1A /* PaypalButton.swift */; };
D9708B5C29E4CCCB004306FA /* OWSDeviceManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9708B5B29E4CCCB004306FA /* OWSDeviceManagerTest.swift */; };
D972E2FF2C542BCD001D7337 /* Backup.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = D972E2FE2C542BCD001D7337 /* Backup.pb.swift */; };
D97411BB28D277C900BB1865 /* GroupManager+GenericGroupUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D97411BA28D277C900BB1865 /* GroupManager+GenericGroupUpdates.swift */; };
D979CC262AD3933B006AAC49 /* IndividualCallRecordManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D979CC1F2AD3933B006AAC49 /* IndividualCallRecordManager.swift */; };
D979CC282AD3933B006AAC49 /* ThreadStore+CallRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = D979CC212AD3933B006AAC49 /* ThreadStore+CallRecord.swift */; };
@@ -1955,7 +1956,6 @@
D9C0AE672BD7162300FCB05E /* InactiveLinkedDeviceFinderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C0AE612BD7102500FCB05E /* InactiveLinkedDeviceFinderTest.swift */; };
D9C0AE692BD82DBC00FCB05E /* InactiveLinkedDeviceReminderMegaphone.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C0AE682BD82DBC00FCB05E /* InactiveLinkedDeviceReminderMegaphone.swift */; };
D9C0AE6B2BDB212F00FCB05E /* MessageBackupLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C0AE6A2BDB212F00FCB05E /* MessageBackupLogger.swift */; };
D9C0AE6D2BDC520000FCB05E /* BackupProto.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C0AE6C2BDC520000FCB05E /* BackupProto.swift */; };
D9C0AE6F2BDC6B3800FCB05E /* MessageBackupIndividualCallArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C0AE6E2BDC6B3800FCB05E /* MessageBackupIndividualCallArchiver.swift */; };
D9C2D77E299D750200D79715 /* UsernameEducationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C2D77D299D750200D79715 /* UsernameEducationManager.swift */; };
D9C2D780299EC11400D79715 /* CreateUsernameMegaphone.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C2D77F299EC11400D79715 /* CreateUsernameMegaphone.swift */; };
@@ -4833,7 +4833,6 @@
D24B5BD4169F568C00681372 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = ../../../../../../System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<group>"; };
D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
D90D4C822BB633560097C573 /* Backup.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = Backup.proto; sourceTree = "<group>"; };
D90D4D6D2BBB45870097C573 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
D90D4D832BBB61680097C573 /* MessageBackupEmptyFrameId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupEmptyFrameId.swift; sourceTree = "<group>"; };
D9106DFE2AC1FEFD007ABFE6 /* EmptyForCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyForCodable.swift; sourceTree = "<group>"; };
D9106E002AC20061007ABFE6 /* EmptyForCodableTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyForCodableTest.swift; sourceTree = "<group>"; };
@@ -4918,6 +4917,7 @@
D95DA7EC28B560D1003996BA /* ConversationViewController+SystemMessageItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConversationViewController+SystemMessageItems.swift"; sourceTree = "<group>"; };
D962346C2C0E957800DAF6CB /* DeleteForMeMostRecentAddressableMessageCursor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteForMeMostRecentAddressableMessageCursor.swift; sourceTree = "<group>"; };
D962346F2C0E99DE00DAF6CB /* DeleteForMeMostRecentAddressableMessageCursorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteForMeMostRecentAddressableMessageCursorTest.swift; sourceTree = "<group>"; };
D96269D82C58407400152314 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
D9668B34291B088200665298 /* SignalMessagingJobQueues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalMessagingJobQueues.swift; sourceTree = "<group>"; };
D968F7192C3355AA00AB318B /* simple-chat-update-message.binproto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "simple-chat-update-message.binproto"; path = "Signal-Message-Backup-Tests/test-cases/simple-chat-update-message.binproto"; sourceTree = "<group>"; };
D968F71A2C3355AB00AB318B /* simple-chat-update-message.jsonproto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "simple-chat-update-message.jsonproto"; path = "Signal-Message-Backup-Tests/test-cases/simple-chat-update-message.jsonproto"; sourceTree = "<group>"; };
@@ -4926,6 +4926,7 @@
D96A94A82955270D004EA434 /* Stripe+Subscriptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stripe+Subscriptions.swift"; sourceTree = "<group>"; };
D96BE42D292EF04200E4FE1A /* PaypalButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaypalButton.swift; sourceTree = "<group>"; };
D9708B5B29E4CCCB004306FA /* OWSDeviceManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSDeviceManagerTest.swift; sourceTree = "<group>"; };
D972E2FE2C542BCD001D7337 /* Backup.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Backup.pb.swift; sourceTree = "<group>"; };
D97411BA28D277C900BB1865 /* GroupManager+GenericGroupUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GroupManager+GenericGroupUpdates.swift"; sourceTree = "<group>"; };
D979CC1F2AD3933B006AAC49 /* IndividualCallRecordManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCallRecordManager.swift; sourceTree = "<group>"; };
D979CC202AD3933B006AAC49 /* IncomingCallEventSyncMessageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IncomingCallEventSyncMessageManager.swift; sourceTree = "<group>"; };
@@ -5022,7 +5023,6 @@
D9C0AE642BD7103100FCB05E /* InactiveLinkedDeviceFinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InactiveLinkedDeviceFinder.swift; sourceTree = "<group>"; };
D9C0AE682BD82DBC00FCB05E /* InactiveLinkedDeviceReminderMegaphone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InactiveLinkedDeviceReminderMegaphone.swift; sourceTree = "<group>"; };
D9C0AE6A2BDB212F00FCB05E /* MessageBackupLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupLogger.swift; sourceTree = "<group>"; };
D9C0AE6C2BDC520000FCB05E /* BackupProto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackupProto.swift; sourceTree = "<group>"; };
D9C0AE6E2BDC6B3800FCB05E /* MessageBackupIndividualCallArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupIndividualCallArchiver.swift; sourceTree = "<group>"; };
D9C2D777299B07D300D79715 /* Usernames+BetterIdentifierChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Usernames+BetterIdentifierChecker.swift"; sourceTree = "<group>"; };
D9C2D77D299D750200D79715 /* UsernameEducationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameEducationManager.swift; sourceTree = "<group>"; };
@@ -9845,9 +9845,9 @@
D90D4C4C2BB633560097C573 /* Backups */ = {
isa = PBXGroup;
children = (
D972E2FE2C542BCD001D7337 /* Backup.pb.swift */,
D90D4C822BB633560097C573 /* Backup.proto */,
D9C0AE6C2BDC520000FCB05E /* BackupProto.swift */,
D90D4D6D2BBB45870097C573 /* README.md */,
D96269D82C58407400152314 /* README.md */,
);
name = Backups;
path = SignalServiceKit/protobuf/Backups;
@@ -12678,7 +12678,7 @@
F9B0DC5C28948656004E07B7 /* GTSR3.crt in Resources */,
F9B0DC5F28948656004E07B7 /* GTSR4.crt in Resources */,
F9B0DC5328948656004E07B7 /* isrgrootx1.der in Resources */,
D90D4D7C2BBB45880097C573 /* README.md in Resources */,
D96269D92C58407400152314 /* README.md in Resources */,
F9B0DC4F28948656004E07B7 /* schema.sql in Resources */,
F9B0DC5928948656004E07B7 /* signal-messenger.cer in Resources */,
);
@@ -12789,7 +12789,6 @@
"${BUILT_PRODUCTS_DIR}/SQLCipher/SQLCipher.framework",
"${BUILT_PRODUCTS_DIR}/SignalRingRTC/SignalRingRTC.framework",
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
"${BUILT_PRODUCTS_DIR}/Wire/Wire.framework",
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
"${BUILT_PRODUCTS_DIR}/blurhash/blurhash.framework",
"${BUILT_PRODUCTS_DIR}/libPhoneNumber-iOS/libPhoneNumber_iOS.framework",
@@ -12813,7 +12812,6 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SQLCipher.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalRingRTC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Wire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/blurhash.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libPhoneNumber_iOS.framework",
@@ -12869,7 +12867,6 @@
"${BUILT_PRODUCTS_DIR}/SQLCipher/SQLCipher.framework",
"${BUILT_PRODUCTS_DIR}/SignalRingRTC/SignalRingRTC.framework",
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
"${BUILT_PRODUCTS_DIR}/Wire/Wire.framework",
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
"${BUILT_PRODUCTS_DIR}/blurhash/blurhash.framework",
"${BUILT_PRODUCTS_DIR}/libPhoneNumber-iOS/libPhoneNumber_iOS.framework",
@@ -12886,7 +12883,6 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SQLCipher.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SignalRingRTC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Wire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/blurhash.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libPhoneNumber_iOS.framework",
@@ -14160,7 +14156,7 @@
7254651E2BA012BD00EABFD2 /* AvatarBuilder.swift in Sources */,
720547F22B9C8F9900E2CF2F /* AvatarModel.swift in Sources */,
502C69722B06F07900012867 /* AwaitableAsyncBlockOperation.swift in Sources */,
D9C0AE6D2BDC520000FCB05E /* BackupProto.swift in Sources */,
D972E2FF2C542BCD001D7337 /* Backup.pb.swift in Sources */,
F9C5CE3A289453B400548EEE /* BadgeAssets.swift in Sources */,
D979DA162B8D1FDD000EEAB8 /* BadgeCountFetcher.swift in Sources */,
F9C5CE37289453B400548EEE /* BadgeStore.swift in Sources */,

View File

@@ -1548,42 +1548,6 @@ limitations under the License.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2014 Alex Crichton
Copyright (c) 2020 Ivan Nikulin &lt;ifaaan@gmail.com&gt;
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</string>
<key>License</key>
<string>MIT License</string>
<key>Title</key>
<string>boring-sys 4.6.0</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2015-2016 the fiat-crypto authors (see
@@ -1635,6 +1599,42 @@ SOFTWARE.</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2014 Alex Crichton
Copyright (c) 2020 Ivan Nikulin &lt;ifaaan@gmail.com&gt;
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</string>
<key>License</key>
<string>MIT License</string>
<key>Title</key>
<string>boring-sys 4.6.0</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>/* ====================================================================
@@ -3035,42 +3035,6 @@ DEALINGS IN THE SOFTWARE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
<key>License</key>
<string>BSD 3-Clause "New" or "Revised" License</string>
<key>Title</key>
<string>curve25519-dalek 4.1.3</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2016-2021 isis agora lovecruft. All rights reserved.
@@ -3101,6 +3065,42 @@ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
<key>License</key>
<string>BSD 3-Clause "New" or "Revised" License</string>
<key>Title</key>
<string>curve25519-dalek 4.1.3</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
<key>License</key>
<string>BSD 3-Clause "New" or "Revised" License</string>
@@ -13126,218 +13126,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</string>
<key>License</key>
<string>apache2</string>
<key>Title</key>
<string>Wire</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Copyright (c) 2017-2021 isis agora lovecruft. All rights reserved.

View File

@@ -4,7 +4,7 @@
//
extension MessageBackup {
/// An identifier for the ``BackupProto.AccountData`` backup frame.
/// An identifier for the ``BackupProto_AccountData`` backup frame.
///
/// Uses a singleton pattern, as there is only ever one account data frame
/// in a backup.
@@ -15,7 +15,7 @@ extension MessageBackup {
// MARK: MessageBackupLoggableId
public var typeLogString: String { "BackupProto.AccountData" }
public var typeLogString: String { "BackupProto_AccountData" }
public var idLogString: String { "localUser" }
}
@@ -24,7 +24,7 @@ extension MessageBackup {
}
/**
* Archives the ``BackupProto.AccountData`` frame
* Archives the ``BackupProto_AccountData`` frame
*/
public protocol MessageBackupAccountDataArchiver: MessageBackupProtoArchiver {
func archiveAccountData(
@@ -33,7 +33,7 @@ public protocol MessageBackupAccountDataArchiver: MessageBackupProtoArchiver {
) -> MessageBackup.ArchiveAccountDataResult
func restore(
_ accountData: BackupProto.AccountData,
_ accountData: BackupProto_AccountData,
tx: DBWriteTransaction
) -> MessageBackup.RestoreAccountDataResult
}
@@ -102,18 +102,19 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
return .failure(.archiveFrameError(.missingLocalProfileKey, .localUser))
}
var accountData = BackupProto.AccountData(
profileKey: profileKeyData,
givenName: localProfile.givenName ?? "",
familyName: localProfile.familyName ?? "",
avatarUrlPath: localProfile.avatarUrlPath ?? ""
)
var accountData = BackupProto_AccountData()
accountData.profileKey = profileKeyData
accountData.givenName = localProfile.givenName ?? ""
accountData.familyName = localProfile.familyName ?? ""
accountData.avatarURLPath = localProfile.avatarUrlPath ?? ""
if let donationSubscriberId = subscriptionManager.getSubscriberID(tx: tx) {
accountData.donationSubscriberData = BackupProto.AccountData.SubscriberData(
subscriberId: donationSubscriberId,
currencyCode: subscriptionManager.getSubscriberCurrencyCode(tx: tx) ?? "",
manuallyCancelled: subscriptionManager.userManuallyCancelledSubscription(tx: tx)
)
var donationSubscriberData = BackupProto_AccountData.SubscriberData()
donationSubscriberData.subscriberID = donationSubscriberId
donationSubscriberData.currencyCode = subscriptionManager.getSubscriberCurrencyCode(tx: tx) ?? ""
donationSubscriberData.manuallyCancelled = subscriptionManager.userManuallyCancelledSubscription(tx: tx)
accountData.donationSubscriberData = donationSubscriberData
}
if let result = buildUsernameLinkProto(tx: tx) {
@@ -124,7 +125,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
accountData.accountSettings = buildAccountSettingsProto(tx: tx)
let error = Self.writeFrameToStream(stream, objectId: MessageBackup.AccountDataId.localUser) {
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .account(accountData)
return frame
}
@@ -136,20 +137,21 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
}
}
private func buildUsernameLinkProto(tx: DBReadTransaction) -> (username: String, usernameLink: BackupProto.AccountData.UsernameLink)? {
private func buildUsernameLinkProto(tx: DBReadTransaction) -> (username: String, usernameLink: BackupProto_AccountData.UsernameLink)? {
switch self.localUsernameManager.usernameState(tx: tx) {
case .unset, .linkCorrupted, .usernameAndLinkCorrupted:
return nil
case .available(let username, let usernameLink):
return (username, BackupProto.AccountData.UsernameLink(
entropy: usernameLink.entropy,
serverId: usernameLink.handle.data,
color: localUsernameManager.usernameLinkQRCodeColor(tx: tx).backupProtoColor
))
var usernameLinkProto = BackupProto_AccountData.UsernameLink()
usernameLinkProto.entropy = usernameLink.entropy
usernameLinkProto.serverID = usernameLink.handle.data
usernameLinkProto.color = localUsernameManager.usernameLinkQRCodeColor(tx: tx).backupProtoColor
return (username, usernameLinkProto)
}
}
private func buildAccountSettingsProto(tx: DBReadTransaction) -> BackupProto.AccountData.AccountSettings {
private func buildAccountSettingsProto(tx: DBReadTransaction) -> BackupProto_AccountData.AccountSettings {
// Fetch all the account settings
let readReceipts = receiptManager.areReadReceiptsEnabled(tx: tx)
@@ -169,30 +171,29 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
let storiesDisabled = storyManager.areStoriesEnabled(tx: tx).negated
let hasSeenGroupStoryEducationSheet = systemStoryManager.hasSeenGroupStoryEducationSheet(tx: tx)
let hasCompletedUsernameOnboarding = usernameEducationManager.shouldShowUsernameEducation(tx: tx).negated
let phoneNumberSharingMode: BackupProto.AccountData.PhoneNumberSharingMode = switch udManager.phoneNumberSharingMode(tx: tx) {
case .everybody: .EVERYBODY
case .nobody: .NOBODY
case .none: .UNKNOWN
let phoneNumberSharingMode: BackupProto_AccountData.PhoneNumberSharingMode = switch udManager.phoneNumberSharingMode(tx: tx) {
case .everybody: .everybody
case .nobody: .nobody
case .none: .unknown
}
// Populate the proto with the settings
var accountSettings = BackupProto.AccountData.AccountSettings(
readReceipts: readReceipts,
sealedSenderIndicators: sealedSenderIndicators,
typingIndicators: typingIndicatorsEnabled,
linkPreviews: linkPreviews,
notDiscoverableByPhoneNumber: notDiscoverableByPhoneNumber,
preferContactAvatars: preferContactAvatars,
universalExpireTimerSeconds: universalExpireTimerSeconds,
displayBadgesOnProfile: displayBadgesOnProfile,
keepMutedChatsArchived: keepMutedChatsArchived,
hasSetMyStoriesPrivacy: hasSetMyStoriesPrivacy,
hasViewedOnboardingStory: hasViewedOnboardingStory,
storiesDisabled: storiesDisabled,
hasSeenGroupStoryEducationSheet: hasSeenGroupStoryEducationSheet,
hasCompletedUsernameOnboarding: hasCompletedUsernameOnboarding,
phoneNumberSharingMode: phoneNumberSharingMode
)
var accountSettings = BackupProto_AccountData.AccountSettings()
accountSettings.readReceipts = readReceipts
accountSettings.sealedSenderIndicators = sealedSenderIndicators
accountSettings.typingIndicators = typingIndicatorsEnabled
accountSettings.linkPreviews = linkPreviews
accountSettings.notDiscoverableByPhoneNumber = notDiscoverableByPhoneNumber
accountSettings.preferContactAvatars = preferContactAvatars
accountSettings.universalExpireTimerSeconds = universalExpireTimerSeconds
accountSettings.displayBadgesOnProfile = displayBadgesOnProfile
accountSettings.keepMutedChatsArchived = keepMutedChatsArchived
accountSettings.hasSetMyStoriesPrivacy_p = hasSetMyStoriesPrivacy
accountSettings.hasViewedOnboardingStory_p = hasViewedOnboardingStory
accountSettings.storiesDisabled = storiesDisabled
accountSettings.hasSeenGroupStoryEducationSheet_p = hasSeenGroupStoryEducationSheet
accountSettings.hasCompletedUsernameOnboarding_p = hasCompletedUsernameOnboarding
accountSettings.phoneNumberSharingMode = phoneNumberSharingMode
accountSettings.preferredReactionEmoji = reactionManager.customEmojiSet(tx: tx) ?? []
accountSettings.storyViewReceiptsEnabled = storyManager.areViewReceiptsEnabled(tx: tx)
// TODO: [Backups] Archive default chat style
@@ -202,7 +203,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
}
public func restore(
_ accountData: BackupProto.AccountData,
_ accountData: BackupProto_AccountData,
tx: DBWriteTransaction
) -> MessageBackup.RestoreAccountDataResult {
guard let profileKey = OWSAES256Key(data: accountData.profileKey) else {
@@ -217,20 +218,22 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
profileManager.insertLocalUserProfile(
givenName: accountData.givenName,
familyName: accountData.familyName.nilIfEmpty,
avatarUrlPath: accountData.avatarUrlPath.nilIfEmpty,
avatarUrlPath: accountData.avatarURLPath.nilIfEmpty,
profileKey: profileKey,
tx: tx
)
// Restore donation subscription data, if present.
if let donationSubscriberData = accountData.donationSubscriberData {
subscriptionManager.setSubscriberID(subscriberID: donationSubscriberData.subscriberId, tx: tx)
if accountData.hasDonationSubscriberData {
let donationSubscriberData = accountData.donationSubscriberData
subscriptionManager.setSubscriberID(subscriberID: donationSubscriberData.subscriberID, tx: tx)
subscriptionManager.setSubscriberCurrencyCode(currencyCode: donationSubscriberData.currencyCode, tx: tx)
subscriptionManager.setUserManuallyCancelledSubscription(value: donationSubscriberData.manuallyCancelled, tx: tx)
}
// Restore local settings
if let settings = accountData.accountSettings {
if accountData.hasAccountSettings {
let settings = accountData.accountSettings
receiptManager.setAreReadReceiptsEnabled(value: settings.readReceipts, tx: tx)
preferences.setShouldShowUnidentifiedDeliveryIndicators(value: settings.sealedSenderIndicators, tx: tx)
typingIndicators.setTypingIndicatorsEnabled(value: settings.typingIndicators, tx: tx)
@@ -256,22 +259,22 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
}
subscriptionManager.setDisplayBadgesOnProfile(value: settings.displayBadgesOnProfile, tx: tx)
sskPreferences.setShouldKeepMutedChatsArchived(value: settings.keepMutedChatsArchived, tx: tx)
storyManager.setHasSetMyStoriesPrivacy(value: settings.hasSetMyStoriesPrivacy, tx: tx)
systemStoryManager.setHasViewedOnboardingStory(value: settings.hasViewedOnboardingStory, tx: tx)
storyManager.setHasSetMyStoriesPrivacy(value: settings.hasSetMyStoriesPrivacy_p, tx: tx)
systemStoryManager.setHasViewedOnboardingStory(value: settings.hasViewedOnboardingStory_p, tx: tx)
storyManager.setAreStoriesEnabled(value: settings.storiesDisabled.negated, tx: tx)
if let storyViewReceiptsEnabled = settings.storyViewReceiptsEnabled {
storyManager.setAreViewReceiptsEnabled(value: storyViewReceiptsEnabled, tx: tx)
if settings.hasStoryViewReceiptsEnabled {
storyManager.setAreViewReceiptsEnabled(value: settings.storyViewReceiptsEnabled, tx: tx)
}
systemStoryManager.setHasSeenGroupStoryEducationSheet(value: settings.hasSeenGroupStoryEducationSheet, tx: tx)
usernameEducationManager.setShouldShowUsernameEducation(settings.hasCompletedUsernameOnboarding.negated, tx: tx)
systemStoryManager.setHasSeenGroupStoryEducationSheet(value: settings.hasSeenGroupStoryEducationSheet_p, tx: tx)
usernameEducationManager.setShouldShowUsernameEducation(settings.hasCompletedUsernameOnboarding_p.negated, tx: tx)
udManager.setPhoneNumberSharingMode(
mode: { () -> PhoneNumberSharingMode in
switch settings.phoneNumberSharingMode {
case .UNKNOWN:
case .unknown, .UNRECOGNIZED:
return .defaultValue
case .EVERYBODY:
case .everybody:
return .everybody
case .NOBODY:
case .nobody:
return .nobody
}
}(),
@@ -282,19 +285,20 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
}
// Restore username details (username, link, QR color)
if let username = accountData.username, let usernameLink = accountData.usernameLink {
if accountData.hasUsername, accountData.hasUsernameLink {
let username = accountData.username
let usernameLink = accountData.usernameLink
if
let handle = UUID(data: usernameLink.serverId),
let handle = UUID(data: usernameLink.serverID),
let linkData = Usernames.UsernameLink(handle: handle, entropy: usernameLink.entropy)
{
localUsernameManager.setLocalUsername(username: username, usernameLink: linkData, tx: tx)
} else {
return .failure([.restoreFrameError(.invalidProtoData(.invalidLocalUsernameLink), .localUser)])
}
}
if let color = accountData.usernameLink?.color {
localUsernameManager.setUsernameLinkQRCodeColor(color: color.qrCodeColor, tx: tx)
localUsernameManager.setUsernameLinkQRCodeColor(color: usernameLink.color.qrCodeColor, tx: tx)
}
return .success
@@ -302,32 +306,32 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi
}
private extension Usernames.QRCodeColor {
var backupProtoColor: BackupProto.AccountData.UsernameLink.Color {
var backupProtoColor: BackupProto_AccountData.UsernameLink.Color {
switch self {
case .blue: return .BLUE
case .white: return .WHITE
case .grey: return .GREY
case .olive: return .OLIVE
case .green: return .GREEN
case .orange: return .ORANGE
case .pink: return .PINK
case .purple: return .PURPLE
case .blue: return .blue
case .white: return .white
case .grey: return .grey
case .olive: return .olive
case .green: return .green
case .orange: return .orange
case .pink: return .pink
case .purple: return .purple
}
}
}
private extension BackupProto.AccountData.UsernameLink.Color {
private extension BackupProto_AccountData.UsernameLink.Color {
var qrCodeColor: Usernames.QRCodeColor {
switch self {
case .BLUE: return .blue
case .WHITE: return .white
case .GREY: return .grey
case .OLIVE: return .olive
case .GREEN: return .green
case .ORANGE: return .orange
case .PINK: return .pink
case .PURPLE: return .purple
case .UNKNOWN: return .unknown
case .blue: return .blue
case .white: return .white
case .grey: return .grey
case .olive: return .olive
case .green: return .green
case .orange: return .orange
case .pink: return .pink
case .purple: return .purple
case .unknown, .UNRECOGNIZED: return .unknown
}
}
}

View File

@@ -18,7 +18,7 @@ extension MessageBackup {
// MARK: MessageBackupLoggableId
public var typeLogString: String { "BackupProto.CallLink" }
public var typeLogString: String { "BackupProto_CallLink" }
public var idLogString: String {
/// Since call IDs are a cross-client identifier, we don't want to
/// log them directly.

View File

@@ -15,17 +15,17 @@ extension MessageBackup {
self.value = value
}
fileprivate init(chat: BackupProto.Chat) {
fileprivate init(chat: BackupProto_Chat) {
self.init(value: chat.id)
}
fileprivate init(chatItem: BackupProto.ChatItem) {
self.init(value: chatItem.chatId)
fileprivate init(chatItem: BackupProto_ChatItem) {
self.init(value: chatItem.chatID)
}
// MARK: MessageBackupLoggableId
public var typeLogString: String { "BackupProto.Chat" }
public var typeLogString: String { "BackupProto_Chat" }
public var idLogString: String { "\(value)" }
}
@@ -81,7 +81,7 @@ extension MessageBackup {
* to the ID addressing system of the backup protos.
*
* For example, we will assign a ``MessageBackup/ChatId`` to each ``TSThread`` as we
* insert them. Later, when we create the ``BackupProto.ChatItem`` corresponding to the ``TSThread``,
* insert them. Later, when we create the ``BackupProto_ChatItem`` corresponding to the ``TSThread``,
* we will need to add the corresponding ``MessageBackup/ChatId``, which we look up using the thread id
* this context keeps.
*/
@@ -157,14 +157,14 @@ extension MessageBackup {
}
}
extension BackupProto.Chat {
extension BackupProto_Chat {
public var chatId: MessageBackup.ChatId {
return MessageBackup.ChatId(chat: self)
}
}
extension BackupProto.ChatItem {
extension BackupProto_ChatItem {
public var typedChatId: MessageBackup.ChatId {
return MessageBackup.ChatId(chatItem: self)

View File

@@ -14,7 +14,7 @@ public protocol MessageBackupChatArchiver: MessageBackupProtoArchiver {
typealias RestoreFrameResult = MessageBackup.RestoreFrameResult<ChatId>
/// Archive all ``TSThread``s (they map to ``BackupProto.Chat``).
/// Archive all ``TSThread``s (they map to ``BackupProto_Chat``).
///
/// - Returns: ``ArchiveMultiFrameResult.success`` if all frames were written without error, or either
/// partial or complete failure otherwise.
@@ -28,13 +28,13 @@ public protocol MessageBackupChatArchiver: MessageBackupProtoArchiver {
tx: DBReadTransaction
) -> ArchiveMultiFrameResult
/// Restore a single ``BackupProto.Chat`` frame.
/// Restore a single ``BackupProto_Chat`` frame.
///
/// - Returns: ``RestoreFrameResult.success`` if all frames were read without error.
/// How to handle ``RestoreFrameResult.failure`` is up to the caller,
/// but typically an error will be shown to the user, but the restore will be allowed to proceed.
func restore(
_ chat: BackupProto.Chat,
_ chat: BackupProto_Chat,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult
@@ -237,22 +237,21 @@ public class MessageBackupChatArchiverImpl: MessageBackupChatArchiver {
dontNotifyForMentionsIfMuted = true
}
let chat = BackupProto.Chat(
id: chatId.value,
recipientId: recipientId.value,
archived: threadAssociatedData.isArchived,
pinnedOrder: thisThreadPinnedOrder,
expirationTimerMs: UInt64(expirationTimerSeconds * 1000),
muteUntilMs: threadAssociatedData.mutedUntilTimestamp,
markedUnread: threadAssociatedData.isMarkedUnread,
dontNotifyForMentionsIfMuted: dontNotifyForMentionsIfMuted
)
var chat = BackupProto_Chat()
chat.id = chatId.value
chat.recipientID = recipientId.value
chat.archived = threadAssociatedData.isArchived
chat.pinnedOrder = thisThreadPinnedOrder
chat.expirationTimerMs = UInt64(expirationTimerSeconds * 1000)
chat.muteUntilMs = threadAssociatedData.mutedUntilTimestamp
chat.markedUnread = threadAssociatedData.isMarkedUnread
chat.dontNotifyForMentionsIfMuted = dontNotifyForMentionsIfMuted
let error = Self.writeFrameToStream(
stream,
objectId: thread.uniqueThreadIdentifier
) {
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .chat(chat)
return frame
}
@@ -266,7 +265,7 @@ public class MessageBackupChatArchiverImpl: MessageBackupChatArchiver {
// MARK: - Restoring
public func restore(
_ chat: BackupProto.Chat,
_ chat: BackupProto_Chat,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult {

View File

@@ -34,19 +34,19 @@ final class MessageBackupGroupCallArchiver {
tx: tx
)
let groupCallState: BackupProto.GroupCall.State
let groupCallState: BackupProto_GroupCall.State
if let associatedCallRecord {
switch associatedCallRecord.callStatus {
case .group(.generic): groupCallState = .GENERIC
case .group(.joined): groupCallState = .JOINED
case .group(.ringing): groupCallState = .RINGING
case .group(.generic): groupCallState = .generic
case .group(.joined): groupCallState = .joined
case .group(.ringing): groupCallState = .ringing
case .group(.ringingAccepted):
switch associatedCallRecord.callDirection {
case .incoming: groupCallState = .ACCEPTED
case .outgoing: groupCallState = .OUTGOING_RING
case .incoming: groupCallState = .accepted
case .outgoing: groupCallState = .outgoingRing
}
case .group(.ringingDeclined): groupCallState = .DECLINED
case .group(.ringingMissed): groupCallState = .MISSED
case .group(.ringingDeclined): groupCallState = .declined
case .group(.ringingMissed): groupCallState = .missed
case .individual:
return .messageFailure([.archiveFrameError(
.groupCallRecordHadIndividualCallStatus,
@@ -55,7 +55,7 @@ final class MessageBackupGroupCallArchiver {
}
} else {
// This call predates the introduction of call records.
groupCallState = .GENERIC
groupCallState = .generic
}
/// The call record will store the best record of when the call began,
@@ -67,17 +67,18 @@ final class MessageBackupGroupCallArchiver {
/// iOS doesn't currently track this, so we'll default-populate it.
let endedCallTimestamp: UInt64 = 0
var groupCallUpdate = BackupProto.GroupCall(
state: groupCallState,
startedCallTimestamp: startedCallTimestamp,
endedCallTimestamp: endedCallTimestamp
)
groupCallUpdate.callId = associatedCallRecord?.callId
var groupCallUpdate = BackupProto_GroupCall()
groupCallUpdate.state = groupCallState
groupCallUpdate.startedCallTimestamp = startedCallTimestamp
groupCallUpdate.endedCallTimestamp = endedCallTimestamp
if let associatedCallRecord {
groupCallUpdate.callID = associatedCallRecord.callId
}
if let ringerAci = associatedCallRecord?.groupCallRingerAci {
switch context.recipientContext.getRecipientId(aci: ringerAci, forInteraction: groupCallInteraction) {
case .found(let recipientId):
groupCallUpdate.ringerRecipientId = recipientId.value
groupCallUpdate.ringerRecipientID = recipientId.value
case .missing(let archiveFrameError):
return .messageFailure([archiveFrameError])
}
@@ -86,18 +87,18 @@ final class MessageBackupGroupCallArchiver {
if let creatorAci = groupCallInteraction.creatorUuid.flatMap({ Aci.parseFrom(aciString: $0) }) {
switch context.recipientContext.getRecipientId(aci: creatorAci, forInteraction: groupCallInteraction) {
case .found(let recipientId):
groupCallUpdate.startedCallRecipientId = recipientId.value
groupCallUpdate.startedCallRecipientID = recipientId.value
case .missing(let archiveFrameError):
return .messageFailure([archiveFrameError])
}
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .groupCall(groupCallUpdate)
let interactionArchiveDetails = Details(
author: context.recipientContext.localRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -108,8 +109,8 @@ final class MessageBackupGroupCallArchiver {
}
func restoreGroupCall(
_ groupCall: BackupProto.GroupCall,
chatItem: BackupProto.ChatItem,
_ groupCall: BackupProto_GroupCall,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
@@ -126,9 +127,9 @@ final class MessageBackupGroupCallArchiver {
}
let startedCallAci: Aci?
if let startedCallRecipientId = groupCall.startedCallRecipientId {
if groupCall.hasStartedCallRecipientID {
switch context.recipientContext.getAci(
recipientId: MessageBackup.RecipientId(value: startedCallRecipientId),
recipientId: MessageBackup.RecipientId(value: groupCall.startedCallRecipientID),
forChatItemId: chatItem.id
) {
case .found(let aci): startedCallAci = aci
@@ -146,39 +147,39 @@ final class MessageBackupGroupCallArchiver {
)
interactionStore.insertInteraction(groupCallInteraction, tx: tx)
if let callId = groupCall.callId {
if groupCall.hasCallID {
let callDirection: CallRecord.CallDirection
let callStatus: CallRecord.CallStatus.GroupCallStatus
switch groupCall.state {
case .UNKNOWN_STATE:
case .unknownState, .UNRECOGNIZED:
return .messageFailure([.restoreFrameError(.invalidProtoData(.groupCallUnrecognizedState), chatItem.id)])
case .GENERIC:
case .generic:
callDirection = .incoming
callStatus = .generic
case .JOINED:
case .joined:
callDirection = .incoming
callStatus = .joined
case .RINGING:
case .ringing:
callDirection = .incoming
callStatus = .ringing
case .ACCEPTED:
case .accepted:
callDirection = .incoming
callStatus = .ringingAccepted
case .DECLINED:
case .declined:
callDirection = .incoming
callStatus = .ringingDeclined
case .MISSED, .MISSED_NOTIFICATION_PROFILE:
case .missed, .missedNotificationProfile:
callDirection = .incoming
callStatus = .ringingMissed
case .OUTGOING_RING:
case .outgoingRing:
callDirection = .outgoing
callStatus = .ringingAccepted
}
let groupCallRingerAci: Aci?
if let ringerRecipientId = groupCall.ringerRecipientId {
if groupCall.hasRingerRecipientID {
switch context.recipientContext.getAci(
recipientId: MessageBackup.RecipientId(value: ringerRecipientId),
recipientId: MessageBackup.RecipientId(value: groupCall.ringerRecipientID),
forChatItemId: chatItem.id
) {
case .found(let aci): groupCallRingerAci = aci
@@ -189,7 +190,7 @@ final class MessageBackupGroupCallArchiver {
}
_ = groupCallRecordManager.createGroupCallRecord(
callId: callId,
callId: groupCall.callID,
groupCallInteraction: groupCallInteraction,
groupCallInteractionRowId: groupCallInteraction.sqliteRowId!,
groupThread: groupThread,

View File

@@ -32,67 +32,68 @@ final class MessageBackupIndividualCallArchiver {
tx: tx
)
var individualCallUpdate = BackupProto.IndividualCall(
type: { () -> BackupProto.IndividualCall.Type_ in
switch individualCallInteraction.offerType {
case .audio: return .AUDIO_CALL
case .video: return .VIDEO_CALL
}
}(),
direction: { () -> BackupProto.IndividualCall.Direction in
switch individualCallInteraction.callType {
case
.incoming,
.incomingIncomplete,
.incomingMissed,
.incomingMissedBecauseOfChangedIdentity,
.incomingMissedBecauseOfDoNotDisturb,
.incomingMissedBecauseBlockedSystemContact,
.incomingDeclined,
.incomingDeclinedElsewhere,
.incomingAnsweredElsewhere,
.incomingBusyElsewhere:
return .INCOMING
case .outgoing, .outgoingIncomplete, .outgoingMissed:
return .OUTGOING
@unknown default:
return .UNKNOWN_DIRECTION
}
}(),
state: { () -> BackupProto.IndividualCall.State in
switch individualCallInteraction.callType {
case .incoming, .outgoing:
return .ACCEPTED
case
.outgoingIncomplete,
.incomingIncomplete,
.incomingDeclined,
.incomingDeclinedElsewhere,
.incomingAnsweredElsewhere,
.incomingBusyElsewhere:
return .NOT_ACCEPTED
case
.incomingMissed,
.incomingMissedBecauseOfChangedIdentity,
.incomingMissedBecauseBlockedSystemContact,
.outgoingMissed:
return .MISSED
case .incomingMissedBecauseOfDoNotDisturb:
return .MISSED_NOTIFICATION_PROFILE
@unknown default:
return .UNKNOWN_STATE
}
}(),
startedCallTimestamp: individualCallInteraction.timestamp
)
individualCallUpdate.callId = associatedCallRecord?.callId
var individualCallUpdate = BackupProto_IndividualCall()
individualCallUpdate.type = { () -> BackupProto_IndividualCall.TypeEnum in
switch individualCallInteraction.offerType {
case .audio: return .audioCall
case .video: return .videoCall
}
}()
individualCallUpdate.direction = { () -> BackupProto_IndividualCall.Direction in
switch individualCallInteraction.callType {
case
.incoming,
.incomingIncomplete,
.incomingMissed,
.incomingMissedBecauseOfChangedIdentity,
.incomingMissedBecauseOfDoNotDisturb,
.incomingMissedBecauseBlockedSystemContact,
.incomingDeclined,
.incomingDeclinedElsewhere,
.incomingAnsweredElsewhere,
.incomingBusyElsewhere:
return .incoming
case .outgoing, .outgoingIncomplete, .outgoingMissed:
return .outgoing
@unknown default:
return .unknownDirection
}
}()
individualCallUpdate.state = { () -> BackupProto_IndividualCall.State in
switch individualCallInteraction.callType {
case .incoming, .outgoing:
return .accepted
case
.outgoingIncomplete,
.incomingIncomplete,
.incomingDeclined,
.incomingDeclinedElsewhere,
.incomingAnsweredElsewhere,
.incomingBusyElsewhere:
return .notAccepted
case
.incomingMissed,
.incomingMissedBecauseOfChangedIdentity,
.incomingMissedBecauseBlockedSystemContact,
.outgoingMissed:
return .missed
case .incomingMissedBecauseOfDoNotDisturb:
return .missedNotificationProfile
@unknown default:
return .unknownState
}
}()
individualCallUpdate.startedCallTimestamp = individualCallInteraction.timestamp
if let associatedCallRecord {
individualCallUpdate.callID = associatedCallRecord.callId
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .individualCall(individualCallUpdate)
let interactionArchiveDetails = Details(
author: context.recipientContext.localRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -103,8 +104,8 @@ final class MessageBackupIndividualCallArchiver {
}
func restoreIndividualCall(
_ individualCall: BackupProto.IndividualCall,
chatItem: BackupProto.ChatItem,
_ individualCall: BackupProto_IndividualCall,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
@@ -124,35 +125,35 @@ final class MessageBackupIndividualCallArchiver {
let callRecordDirection: CallRecord.CallDirection
let callRecordStatus: CallRecord.CallStatus.IndividualCallStatus
switch (individualCall.direction, individualCall.state) {
case (.UNKNOWN_DIRECTION, _):
case (.unknownDirection, _), (.UNRECOGNIZED, _):
return .messageFailure([.restoreFrameError(.invalidProtoData(.individualCallUnrecognizedDirection), chatItem.id)])
case (_, .UNKNOWN_STATE):
case (_, .unknownState), (_, .UNRECOGNIZED):
return .messageFailure([.restoreFrameError(.invalidProtoData(.individualCallUnrecognizedState), chatItem.id)])
case (.INCOMING, .ACCEPTED):
case (.incoming, .accepted):
callInteractionType = .incoming
callRecordDirection = .incoming
callRecordStatus = .accepted
case (.INCOMING, .NOT_ACCEPTED):
case (.incoming, .notAccepted):
callInteractionType = .incomingDeclined
callRecordDirection = .incoming
callRecordStatus = .notAccepted
case (.INCOMING, .MISSED):
case (.incoming, .missed):
callInteractionType = .incomingMissed
callRecordDirection = .incoming
callRecordStatus = .incomingMissed
case (.INCOMING, .MISSED_NOTIFICATION_PROFILE):
case (.incoming, .missedNotificationProfile):
callInteractionType = .incomingMissedBecauseOfDoNotDisturb
callRecordDirection = .incoming
callRecordStatus = .incomingMissed
case (.OUTGOING, .ACCEPTED):
case (.outgoing, .accepted):
callInteractionType = .outgoing
callRecordDirection = .outgoing
callRecordStatus = .accepted
case (.OUTGOING, .NOT_ACCEPTED):
case (.outgoing, .notAccepted):
callInteractionType = .outgoingIncomplete
callRecordDirection = .outgoing
callRecordStatus = .notAccepted
case (.OUTGOING, .MISSED), (.OUTGOING, .MISSED_NOTIFICATION_PROFILE):
case (.outgoing, .missed), (.outgoing, .missedNotificationProfile):
callInteractionType = .outgoingMissed
callRecordDirection = .outgoing
callRecordStatus = .notAccepted
@@ -161,13 +162,13 @@ final class MessageBackupIndividualCallArchiver {
let callInteractionOfferType: TSRecentCallOfferType
let callRecordType: CallRecord.CallType
switch individualCall.type {
case .AUDIO_CALL:
case .audioCall:
callInteractionOfferType = .audio
callRecordType = .audioCall
case .VIDEO_CALL:
case .videoCall:
callInteractionOfferType = .video
callRecordType = .videoCall
case .UNKNOWN_TYPE:
case .unknownType, .UNRECOGNIZED:
return .messageFailure([.restoreFrameError(.invalidProtoData(.individualCallUnrecognizedType), chatItem.id)])
}
@@ -179,13 +180,13 @@ final class MessageBackupIndividualCallArchiver {
)
interactionStore.insertInteraction(individualCallInteraction, tx: tx)
if let callId = individualCall.callId {
if individualCall.hasCallID {
individualCallRecordManager.createRecordForInteraction(
individualCallInteraction: individualCallInteraction,
individualCallInteractionRowId: individualCallInteraction.sqliteRowId!,
contactThread: contactThread,
contactThreadRowId: chatThread.threadRowId,
callId: callId,
callId: individualCall.callID,
callType: callRecordType,
callDirection: callRecordDirection,
individualCallStatus: callRecordStatus,

View File

@@ -74,7 +74,7 @@ final class MessageBackupGroupUpdateMessageArchiver {
localIdentifiers: context.recipientContext.localIdentifiers,
partialErrors: &partialErrors
)
let groupChange: BackupProto.GroupChangeChatUpdate
let groupChange: BackupProto_GroupChangeChatUpdate
switch contentsResult.bubbleUp(Details.self, partialErrors: &partialErrors) {
case .continue(let groupUpdate):
groupChange = groupUpdate
@@ -82,10 +82,10 @@ final class MessageBackupGroupUpdateMessageArchiver {
return errorResult
}
var chatUpdate = BackupProto.ChatUpdateMessage()
var chatUpdate = BackupProto_ChatUpdateMessage()
chatUpdate.update = .groupChange(groupChange)
let directionlessDetails = BackupProto.ChatItem.DirectionlessMessageDetails()
let directionlessDetails = BackupProto_ChatItem.DirectionlessMessageDetails()
let details = Details(
author: context.recipientContext.localRecipientId,
@@ -108,8 +108,8 @@ final class MessageBackupGroupUpdateMessageArchiver {
interactionId: MessageBackup.InteractionUniqueId,
localIdentifiers: LocalIdentifiers,
partialErrors: inout [ArchiveFrameError]
) -> MessageBackup.ArchiveInteractionResult<BackupProto.GroupChangeChatUpdate> {
var updates = [BackupProto.GroupChangeChatUpdate.Update]()
) -> MessageBackup.ArchiveInteractionResult<BackupProto_GroupChangeChatUpdate> {
var updates = [BackupProto_GroupChangeChatUpdate.Update]()
var skipCount = 0
var latestSkipError: MessageBackup.SkippableChatUpdate.SkippableGroupUpdate?
@@ -121,7 +121,7 @@ final class MessageBackupGroupUpdateMessageArchiver {
interactionId: interactionId
)
switch result.bubbleUp(
BackupProto.GroupChangeChatUpdate.self,
BackupProto_GroupChangeChatUpdate.self,
partialErrors: &partialErrors
) {
case .continue(let update):
@@ -146,7 +146,7 @@ final class MessageBackupGroupUpdateMessageArchiver {
return .messageFailure(partialErrors + [.archiveFrameError(.emptyGroupUpdate, interactionId)])
}
var groupChangeChatUpdate = BackupProto.GroupChangeChatUpdate()
var groupChangeChatUpdate = BackupProto_GroupChangeChatUpdate()
groupChangeChatUpdate.updates = updates
if partialErrors.isEmpty {
@@ -157,8 +157,8 @@ final class MessageBackupGroupUpdateMessageArchiver {
}
func restoreGroupUpdate(
_ groupUpdate: BackupProto.GroupChangeChatUpdate,
chatItem: BackupProto.ChatItem,
_ groupUpdate: BackupProto_GroupChangeChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction

View File

@@ -6,14 +6,14 @@
import Foundation
import LibSignalClient
internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
final class MessageBackupGroupUpdateProtoToSwiftConverter {
private init() {}
typealias PersistableGroupUpdateItem = TSInfoMessage.PersistableGroupUpdateItem
internal static func restoreGroupUpdates(
groupUpdates: [BackupProto.GroupChangeChatUpdate.Update],
static func restoreGroupUpdates(
groupUpdates: [BackupProto_GroupChangeChatUpdate.Update],
// We should never be comparing our pni as it can change,
// we only ever want to compare our unchanging aci.
localUserAci: Aci,
@@ -37,54 +37,58 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
private static func restoreGroupUpdate(
groupUpdate: BackupProto.GroupChangeChatUpdate.Update,
groupUpdate: BackupProto_GroupChangeChatUpdate.Update,
localUserAci: Aci,
chatItemId: MessageBackup.ChatItemId
) -> MessageBackup.RestoreInteractionResult<[PersistableGroupUpdateItem]> {
enum UnwrappedAci {
enum UnwrappedRequiredAci {
case localUser
case otherUser(AciUuid)
case invalidAci(MessageBackup.RestoreFrameError<MessageBackup.ChatItemId>)
}
enum UnwrappedOptionalAci {
case unknown
case localUser
case otherUser(AciUuid)
case invalidAci(MessageBackup.RestoreFrameError<MessageBackup.ChatItemId>)
}
func unwrapAci<Proto>(
func unwrapRequiredAci<Proto>(
_ proto: Proto,
_ aciKeyPath: KeyPath<Proto, Data>
) -> UnwrappedAci {
) -> UnwrappedRequiredAci {
let aciData = proto[keyPath: aciKeyPath]
guard let aciUuid = UUID(data: aciData) else {
guard let aci = UUID(data: aciData).map({ Aci(fromUUID: $0) }) else {
return .invalidAci(.restoreFrameError(
.invalidProtoData(.invalidAci(protoClass: Proto.self)),
chatItemId
))
}
let aci = Aci(fromUUID: aciUuid)
if aci == localUserAci {
return .localUser
} else {
return .otherUser(aci.codableUuid)
}
}
func unwrapAci<Proto>(
enum UnwrappedOptionalAci {
case unknown
case localUser
case otherUser(AciUuid)
case invalidAci(MessageBackup.RestoreFrameError<MessageBackup.ChatItemId>)
}
func unwrapOptionalAci<Proto>(
_ proto: Proto,
_ aciKeyPath: KeyPath<Proto, Data?>
_ aciKeyPath: KeyPath<Proto, Data>
) -> UnwrappedOptionalAci {
guard let aciData = proto[keyPath: aciKeyPath] else {
let aciData = proto[keyPath: aciKeyPath]
guard !aciData.isEmpty else {
return .unknown
}
guard let aciUuid = UUID(data: aciData) else {
guard let aci = UUID(data: aciData).map({ Aci(fromUUID: $0) }) else {
return .invalidAci(.restoreFrameError(
.invalidProtoData(.invalidAci(protoClass: Proto.self)),
chatItemId
))
}
let aci = Aci(fromUUID: aciUuid)
if aci == localUserAci {
return .localUser
} else {
@@ -93,10 +97,10 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
switch groupUpdate.update {
case .none:
case nil:
return .messageFailure([.restoreFrameError(.invalidProtoData(.unrecognizedGroupUpdate), chatItemId)])
case .genericGroupUpdate(let proto):
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.genericUpdateByUnknownUser])
case .localUser:
@@ -107,7 +111,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupCreationUpdate(let proto):
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.genericUpdateByUnknownUser])
case .localUser:
@@ -120,8 +124,9 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupNameUpdate(let proto):
if let newName = proto.newGroupName {
switch unwrapAci(proto, \.updaterAci) {
if proto.hasNewGroupName {
let newName = proto.newGroupName
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.nameChangedByUnknownUser(newGroupName: newName)])
case .localUser:
@@ -132,7 +137,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.nameRemovedByUnknownUser])
case .localUser:
@@ -145,7 +150,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupAvatarUpdate(let proto):
if proto.wasRemoved {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.avatarRemovedByUnknownUser])
case .localUser:
@@ -156,7 +161,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.avatarChangedByUnknownUser])
case .localUser:
@@ -168,8 +173,9 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupDescriptionUpdate(let proto):
if let newDescription = proto.newDescription {
switch unwrapAci(proto, \.updaterAci) {
if proto.hasNewDescription {
let newDescription = proto.newDescription
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.descriptionChangedByUnknownUser(newDescription: newDescription)])
case .localUser:
@@ -180,7 +186,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.descriptionRemovedByUnknownUser])
case .localUser:
@@ -193,7 +199,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupMembershipAccessLevelChangeUpdate(let proto):
let newAccess = proto.accessLevel.swiftAccessLevel
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.membersAccessChangedByUnknownUser(newAccess: newAccess)])
case .localUser:
@@ -205,7 +211,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupAttributesAccessLevelChangeUpdate(let proto):
let newAccess = proto.accessLevel.swiftAccessLevel
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.attributesAccessChangedByUnknownUser(newAccess: newAccess)])
case .localUser:
@@ -217,7 +223,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupAnnouncementOnlyChangeUpdate(let proto):
if proto.isAnnouncementOnly {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.announcementOnlyEnabledByUnknownUser])
case .localUser:
@@ -228,7 +234,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.announcementOnlyDisabledByUnknownUser])
case .localUser:
@@ -240,8 +246,8 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupAdminStatusUpdate(let proto):
let updaterAci = unwrapAci(proto, \.updaterAci)
let memberAci = unwrapAci(proto, \.memberAci)
let updaterAci = unwrapOptionalAci(proto, \.updaterAci)
let memberAci = unwrapRequiredAci(proto, \.memberAci)
if proto.wasAdminStatusGranted {
switch (updaterAci, memberAci) {
case (.unknown, .localUser):
@@ -278,7 +284,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupMemberLeftUpdate(let proto):
switch unwrapAci(proto, \.aci) {
switch unwrapRequiredAci(proto, \.aci) {
case .localUser:
return .success([.localUserLeft])
case .otherUser(let aci):
@@ -287,7 +293,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupMemberRemovedUpdate(let proto):
switch (unwrapAci(proto, \.removerAci), unwrapAci(proto, \.removedAci)) {
switch (unwrapOptionalAci(proto, \.removerAci), unwrapRequiredAci(proto, \.removedAci)) {
case (.unknown, .localUser):
return .success([.localUserRemovedByUnknownUser])
case (.localUser, .localUser):
@@ -304,7 +310,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .selfInvitedToGroupUpdate(let proto):
switch unwrapAci(proto, \.inviterAci) {
switch unwrapOptionalAci(proto, \.inviterAci) {
case .unknown:
return .success([.localUserWasInvitedByUnknownUser])
case .localUser:
@@ -315,18 +321,18 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .selfInvitedOtherUserToGroupUpdate(let proto):
switch (try? ServiceId.parseFrom(serviceIdBinary: proto.inviteeServiceId)) {
switch (try? ServiceId.parseFrom(serviceIdBinary: proto.inviteeServiceID)) {
case .some(let serviceId):
return .success([.otherUserWasInvitedByLocalUser(inviteeServiceId: serviceId.codableUppercaseString)])
case .none:
return .messageFailure([.restoreFrameError(
.invalidProtoData(.invalidServiceId(protoClass: BackupProto.SelfInvitedOtherUserToGroupUpdate.self)),
.invalidProtoData(.invalidServiceId(protoClass: BackupProto_SelfInvitedOtherUserToGroupUpdate.self)),
chatItemId
)])
}
case .groupUnknownInviteeUpdate(let proto):
let count = UInt(proto.inviteeCount)
switch unwrapAci(proto, \.inviterAci) {
switch unwrapOptionalAci(proto, \.inviterAci) {
case .unknown:
return .success([.unnamedUsersWereInvitedByUnknownUser(count: count)])
case .localUser:
@@ -337,7 +343,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupInvitationAcceptedUpdate(let proto):
switch (unwrapAci(proto, \.inviterAci), unwrapAci(proto, \.newMemberAci)) {
switch (unwrapOptionalAci(proto, \.inviterAci), unwrapRequiredAci(proto, \.newMemberAci)) {
case (.unknown, .localUser):
return .success([.localUserAcceptedInviteFromUnknownUser])
case (.localUser, .localUser):
@@ -354,7 +360,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupInvitationDeclinedUpdate(let proto):
switch (unwrapAci(proto, \.inviterAci), unwrapAci(proto, \.inviteeAci)) {
switch (unwrapOptionalAci(proto, \.inviterAci), unwrapOptionalAci(proto, \.inviteeAci)) {
case (.unknown, .localUser):
return .success([.localUserDeclinedInviteFromUnknownUser])
case (.localUser, .localUser):
@@ -377,7 +383,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupMemberJoinedUpdate(let proto):
switch unwrapAci(proto, \.newMemberAci) {
switch unwrapRequiredAci(proto, \.newMemberAci) {
case .localUser:
return .success([.localUserJoined])
case .otherUser(let aci):
@@ -386,7 +392,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupMemberAddedUpdate(let proto):
switch (unwrapAci(proto, \.inviterAci), unwrapAci(proto, \.newMemberAci)) {
switch (unwrapOptionalAci(proto, \.inviterAci), unwrapRequiredAci(proto, \.newMemberAci)) {
case (.unknown, .localUser):
return .success([.localUserAddedByUnknownUser])
case (.localUser, .localUser):
@@ -403,7 +409,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupSelfInvitationRevokedUpdate(let proto):
switch unwrapAci(proto, \.revokerAci) {
switch unwrapOptionalAci(proto, \.revokerAci) {
case .unknown:
return .success([.localUserInviteRevokedByUnknownUser])
case .localUser:
@@ -414,20 +420,20 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupInvitationRevokedUpdate(let proto):
let updaterAci = unwrapAci(proto, \.updaterAci)
let updaterAci = unwrapOptionalAci(proto, \.updaterAci)
if
case .localUser = updaterAci,
proto.invitees.count == 1,
let inviteeServiceId: ServiceId = {
let invitee = proto.invitees[0]
if
let aciRaw = invitee.inviteeAci,
let aciUuid = UUID(data: aciRaw)
invitee.hasInviteeAci,
let aciUuid = UUID(data: invitee.inviteeAci)
{
return Aci(fromUUID: aciUuid)
} else if
let pniRaw = invitee.inviteePni,
let pniUuid = UUID(data: pniRaw)
invitee.hasInviteePni,
let pniUuid = UUID(data: invitee.inviteePni)
{
return Pni(fromUUID: pniUuid)
} else {
@@ -452,7 +458,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupJoinRequestUpdate(let proto):
switch unwrapAci(proto, \.requestorAci) {
switch unwrapRequiredAci(proto, \.requestorAci) {
case .localUser:
return .success([.localUserRequestedToJoin])
case .otherUser(let aci):
@@ -462,7 +468,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupJoinRequestApprovalUpdate(let proto):
if proto.wasApproved {
switch (unwrapAci(proto, \.requestorAci), unwrapAci(proto, \.updaterAci)) {
switch (unwrapRequiredAci(proto, \.requestorAci), unwrapOptionalAci(proto, \.updaterAci)) {
case (.localUser, .unknown):
return .success([.localUserRequestApprovedByUnknownUser])
case (.localUser, .localUser):
@@ -479,7 +485,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch (unwrapAci(proto, \.requestorAci), unwrapAci(proto, \.updaterAci)) {
switch (unwrapRequiredAci(proto, \.requestorAci), unwrapOptionalAci(proto, \.updaterAci)) {
case (.localUser, .unknown):
return .success([.localUserRequestRejectedByUnknownUser])
case (.localUser, .localUser):
@@ -498,7 +504,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupJoinRequestCanceledUpdate(let proto):
switch unwrapAci(proto, \.requestorAci) {
switch unwrapRequiredAci(proto, \.requestorAci) {
case .localUser:
return .success([.localUserRequestCanceledByLocalUser])
case .otherUser(let aci):
@@ -507,7 +513,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupInviteLinkResetUpdate(let proto):
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkResetByUnknownUser])
case .localUser:
@@ -519,7 +525,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupInviteLinkEnabledUpdate(let proto):
if proto.linkRequiresAdminApproval {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkEnabledWithApprovalByUnknownUser])
case .localUser:
@@ -530,7 +536,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkEnabledWithoutApprovalByUnknownUser])
case .localUser:
@@ -543,7 +549,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
case .groupInviteLinkAdminApprovalUpdate(let proto):
if proto.linkRequiresAdminApproval {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkApprovalEnabledByUnknownUser])
case .localUser:
@@ -554,7 +560,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkApprovalDisabledByUnknownUser])
case .localUser:
@@ -566,7 +572,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
case .groupInviteLinkDisabledUpdate(let proto):
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.inviteLinkDisabledByUnknownUser])
case .localUser:
@@ -577,7 +583,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
case .groupMemberJoinedByLinkUpdate(let proto):
switch unwrapAci(proto, \.newMemberAci) {
switch unwrapRequiredAci(proto, \.newMemberAci) {
case .localUser:
return .success([.localUserJoinedViaInviteLink])
case .otherUser(let aci):
@@ -594,7 +600,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
case .groupV2MigrationDroppedMembersUpdate(let proto):
return .success([.otherUsersDroppedAfterMigration(count: UInt(proto.droppedMembersCount))])
case .groupSequenceOfRequestsAndCancelsUpdate(let proto):
switch unwrapAci(proto, \.requestorAci) {
switch unwrapRequiredAci(proto, \.requestorAci) {
case .localUser:
return .messageFailure([.restoreFrameError(
.invalidProtoData(.sequenceOfRequestsAndCancelsWithLocalAci),
@@ -610,7 +616,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
case .groupExpirationTimerUpdate(let proto):
let durationMs = proto.expiresInMs
if durationMs > 0 {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.disappearingMessagesEnabledByUnknownUser(durationMs: durationMs)])
case .localUser:
@@ -621,7 +627,7 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
return .messageFailure([error])
}
} else {
switch unwrapAci(proto, \.updaterAci) {
switch unwrapOptionalAci(proto, \.updaterAci) {
case .unknown:
return .success([.disappearingMessagesDisabledByUnknownUser])
case .localUser:
@@ -636,19 +642,19 @@ internal final class MessageBackupGroupUpdateProtoToSwiftConverter {
}
}
extension BackupProto.GroupV2AccessLevel {
extension BackupProto_GroupV2AccessLevel {
fileprivate var swiftAccessLevel: GroupV2Access {
switch self {
case .UNKNOWN:
case .unknown, .UNRECOGNIZED:
return .unknown
case .ANY:
case .any:
return .any
case .MEMBER:
case .member:
return .member
case .ADMINISTRATOR:
case .administrator:
return .administrator
case .UNSATISFIABLE:
case .unsatisfiable:
return .unsatisfiable
}
}

View File

@@ -180,12 +180,12 @@ final class MessageBackupChatUpdateMessageArchiver: MessageBackupInteractionArch
// MARK: -
func restoreChatItem(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction
) -> RestoreChatUpdateMessageResult {
let chatUpdateMessage: BackupProto.ChatUpdateMessage
let chatUpdateMessage: BackupProto_ChatUpdateMessage
do {
switch chatItem.item {
case .updateMessage(let updateMessage):

View File

@@ -77,14 +77,15 @@ final class MessageBackupExpirationTimerChatUpdateArchiver {
chatUpdateAuthorRecipientId = recipientId
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .expirationTimerChange(BackupProto.ExpirationTimerChatUpdate(
expiresInMs: chatUpdateExpiresInMs
))
var expirationTimerChatUpdate = BackupProto_ExpirationTimerChatUpdate()
expirationTimerChatUpdate.expiresInMs = chatUpdateExpiresInMs
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .expirationTimerChange(expirationTimerChatUpdate)
let interactionArchiveDetails = Details(
author: chatUpdateAuthorRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -97,8 +98,8 @@ final class MessageBackupExpirationTimerChatUpdateArchiver {
// MARK: -
func restoreExpirationTimerChatUpdate(
_ expirationTimerChatUpdate: BackupProto.ExpirationTimerChatUpdate,
chatItem: BackupProto.ChatItem,
_ expirationTimerChatUpdate: BackupProto_ExpirationTimerChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction

View File

@@ -51,15 +51,16 @@ final class MessageBackupProfileChangeChatUpdateArchiver {
return messageFailure(.profileChangeUpdateMissingNames)
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .profileChange(BackupProto.ProfileChangeChatUpdate(
previousName: oldProfileName,
newName: newProfileName
))
var profileChangeChatUpdate = BackupProto_ProfileChangeChatUpdate()
profileChangeChatUpdate.previousName = oldProfileName
profileChangeChatUpdate.newName = newProfileName
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .profileChange(profileChangeChatUpdate)
let interactionArchiveDetails = Details(
author: profileRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -72,8 +73,8 @@ final class MessageBackupProfileChangeChatUpdateArchiver {
// MARK: -
func restoreProfileChangeChatUpdate(
_ profileChangeChatUpdateProto: BackupProto.ProfileChangeChatUpdate,
chatItem: BackupProto.ChatItem,
_ profileChangeChatUpdateProto: BackupProto_ProfileChangeChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction

View File

@@ -51,14 +51,15 @@ final class MessageBackupSessionSwitchoverChatUpdateArchiver {
return messageFailure(.referencedRecipientIdMissing(.contact(switchedOverContactAddress)))
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .sessionSwitchover(BackupProto.SessionSwitchoverChatUpdate(
e164: sessionSwitchoverPhoneNumber.uint64Value
))
var sessionSwitchoverChatUpdate = BackupProto_SessionSwitchoverChatUpdate()
sessionSwitchoverChatUpdate.e164 = sessionSwitchoverPhoneNumber.uint64Value
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .sessionSwitchover(sessionSwitchoverChatUpdate)
let interactionArchiveDetails = Details(
author: threadRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -71,8 +72,8 @@ final class MessageBackupSessionSwitchoverChatUpdateArchiver {
// MARK: -
func restoreSessionSwitchoverChatUpdate(
_ sessionSwitchoverUpdateProto: BackupProto.SessionSwitchoverChatUpdate,
chatItem: BackupProto.ChatItem,
_ sessionSwitchoverUpdateProto: BackupProto_SessionSwitchoverChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction
@@ -89,7 +90,7 @@ final class MessageBackupSessionSwitchoverChatUpdateArchiver {
}
guard let e164 = E164(sessionSwitchoverUpdateProto.e164) else {
return invalidProtoData(.invalidE164(protoClass: BackupProto.SessionSwitchoverChatUpdate.self))
return invalidProtoData(.invalidE164(protoClass: BackupProto_SessionSwitchoverChatUpdate.self))
}
guard case .contact(let switchedOverContactThread) = chatThread.threadType else {

View File

@@ -53,7 +53,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
}
let updateAuthor: UpdateAuthor
let updateType: BackupProto.SimpleChatUpdate.Type_
let updateType: BackupProto_SimpleChatUpdate.TypeEnum
switch infoMessage.messageType {
case
@@ -99,9 +99,9 @@ final class MessageBackupSimpleChatUpdateArchiver {
switch verificationStateChangeMessage.verificationState {
case .default, .defaultAcknowledged, .noLongerVerified:
updateType = .IDENTITY_DEFAULT
updateType = .identityDefault
case .verified:
updateType = .IDENTITY_VERIFIED
updateType = .identityVerified
}
case .phoneNumberChange:
guard let changedNumberUserAci = infoMessage.phoneNumberChangeInfo()?.aci else {
@@ -114,7 +114,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
}
updateAuthor = .precomputedRecipientId(recipientId)
updateType = .CHANGE_NUMBER
updateType = .changeNumber
case .paymentsActivationRequest:
switch infoMessage.paymentsActivationRequestAuthor(localIdentifiers: context.recipientContext.localIdentifiers) {
case nil:
@@ -130,7 +130,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
updateAuthor = .precomputedRecipientId(authorRecipientId)
}
updateType = .PAYMENT_ACTIVATION_REQUEST
updateType = .paymentActivationRequest
case .paymentsActivated:
switch infoMessage.paymentsActivatedAuthor(localIdentifiers: context.recipientContext.localIdentifiers) {
case nil:
@@ -146,7 +146,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
updateAuthor = .precomputedRecipientId(authorRecipientId)
}
updateType = .PAYMENTS_ACTIVATED
updateType = .paymentsActivated
case .unknownProtocolVersion:
guard let unknownProtocolVersionMessage = infoMessage as? OWSUnknownProtocolVersionMessage else {
return messageFailure(.unknownProtocolVersionNotExpectedSDSRecordType)
@@ -167,21 +167,21 @@ final class MessageBackupSimpleChatUpdateArchiver {
updateAuthor = .localUser
}
updateType = .UNSUPPORTED_PROTOCOL_MESSAGE
updateType = .unsupportedProtocolMessage
case .typeSessionDidEnd:
// Only inserted for 1:1 threads.
updateAuthor = .containingContactThread
updateType = .END_SESSION
updateType = .endSession
case .userJoinedSignal:
// Only inserted for 1:1 threads.
updateAuthor = .containingContactThread
updateType = .JOINED_SIGNAL
updateType = .joinedSignal
case .reportedSpam:
// The reported-spam info message doesn't contain any info as to
// what message we reported spam. Regardless, we were the one to
// take this action, so we're the author.
updateAuthor = .localUser
updateType = .REPORTED_SPAM
updateType = .reportedSpam
}
let updateAuthorRecipientId: MessageBackup.RecipientId
@@ -204,12 +204,15 @@ final class MessageBackupSimpleChatUpdateArchiver {
updateAuthorRecipientId = context.recipientContext.localRecipientId
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .simpleUpdate(BackupProto.SimpleChatUpdate(type: updateType))
var simpleChatUpdate = BackupProto_SimpleChatUpdate()
simpleChatUpdate.type = updateType
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .simpleUpdate(simpleChatUpdate)
let interactionArchiveDetails = Details(
author: updateAuthorRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -237,7 +240,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
}
let updateAuthor: MessageBackup.ContactAddress
let updateType: BackupProto.SimpleChatUpdate.Type_
let updateType: BackupProto_SimpleChatUpdate.TypeEnum
switch errorMessage.errorType {
case .noSession:
@@ -265,7 +268,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
return messageFailure(.identityKeyChangeInteractionMissingAuthor)
}
updateType = .IDENTITY_UPDATE
updateType = .identityUpdate
updateAuthor = recipientAddress
case .sessionRefresh:
/// These can only happen in contact threads, not group threads.
@@ -278,7 +281,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
return messageFailure(.sessionRefreshInteractionMissingAuthor)
}
updateType = .CHAT_SESSION_REFRESH
updateType = .chatSessionRefresh
updateAuthor = recipientAddress
case .decryptionFailure:
/// This type of error message historically put the person who sent
@@ -287,7 +290,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
return messageFailure(.decryptionErrorInteractionMissingAuthor)
}
updateType = .BAD_DECRYPT
updateType = .badDecrypt
updateAuthor = recipientAddress
}
@@ -295,12 +298,15 @@ final class MessageBackupSimpleChatUpdateArchiver {
return messageFailure(.referencedRecipientIdMissing(.contact(updateAuthor)))
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .simpleUpdate(BackupProto.SimpleChatUpdate(type: updateType))
var simpleChatUpdate = BackupProto_SimpleChatUpdate()
simpleChatUpdate.type = updateType
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .simpleUpdate(simpleChatUpdate)
let interactionArchiveDetails = Details(
author: updateAuthorRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -313,8 +319,8 @@ final class MessageBackupSimpleChatUpdateArchiver {
// MARK: -
func restoreSimpleChatUpdate(
_ simpleChatUpdate: BackupProto.SimpleChatUpdate,
chatItem: BackupProto.ChatItem,
_ simpleChatUpdate: BackupProto_SimpleChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction
@@ -340,11 +346,11 @@ final class MessageBackupSimpleChatUpdateArchiver {
let simpleChatUpdateInteraction: SimpleChatUpdateInteraction
switch simpleChatUpdate.type {
case .UNKNOWN:
case .unknown, .UNRECOGNIZED:
return invalidProtoData(.unrecognizedSimpleChatUpdate)
case .JOINED_SIGNAL:
case .joinedSignal:
simpleChatUpdateInteraction = .simpleInfoMessage(.userJoinedSignal)
case .IDENTITY_UPDATE:
case .identityUpdate:
guard let verificationRecipient = context.recipientContext[chatItem.authorRecipientId] else {
return invalidProtoData(.recipientIdNotFound(chatItem.authorRecipientId))
}
@@ -362,7 +368,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
// backup and it only affects the action shown for the message.
wasIdentityVerified: false
))
case .IDENTITY_VERIFIED, .IDENTITY_DEFAULT:
case .identityVerified, .identityDefault:
guard let verificationRecipient = context.recipientContext[chatItem.authorRecipientId] else {
return invalidProtoData(.recipientIdNotFound(chatItem.authorRecipientId))
}
@@ -371,8 +377,8 @@ final class MessageBackupSimpleChatUpdateArchiver {
}
let verificationState: OWSVerificationState = switch simpleChatUpdate.type {
case .IDENTITY_VERIFIED: .verified
case .IDENTITY_DEFAULT: .default
case .identityVerified: .verified
case .identityDefault: .default
default: owsFail("Impossible: checked above.")
}
@@ -387,7 +393,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
// message is displayed.
isLocalChange: true
))
case .CHANGE_NUMBER:
case .changeNumber:
guard let verificationRecipient = context.recipientContext[chatItem.authorRecipientId] else {
return invalidProtoData(.recipientIdNotFound(chatItem.authorRecipientId))
}
@@ -402,17 +408,17 @@ final class MessageBackupSimpleChatUpdateArchiver {
changeNumberInfoMessage.setPhoneNumberChangeInfo(aci: aci, oldNumber: nil, newNumber: nil)
simpleChatUpdateInteraction = .prebuiltInfoMessage(changeNumberInfoMessage)
case .RELEASE_CHANNEL_DONATION_REQUEST:
case .releaseChannelDonationRequest:
// TODO: [Backups] Add support (and a test case!) for this once we've implemented the Release Notes channel.
logger.warn("Encountered not-yet-supported release-channel-donation-request update")
return .success(())
case .END_SESSION:
case .endSession:
simpleChatUpdateInteraction = .simpleInfoMessage(.typeSessionDidEnd)
case .CHAT_SESSION_REFRESH:
case .chatSessionRefresh:
simpleChatUpdateInteraction = .errorMessage(TSErrorMessage.sessionRefresh(
in: thread
))
case .BAD_DECRYPT:
case .badDecrypt:
guard let senderRecipient = context.recipientContext[chatItem.authorRecipientId] else {
return invalidProtoData(.recipientIdNotFound(chatItem.authorRecipientId))
}
@@ -425,7 +431,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
thread: thread,
timestamp: chatItem.dateSent
))
case .PAYMENTS_ACTIVATED:
case .paymentsActivated:
let senderAci: Aci
switch context.recipientContext[chatItem.authorRecipientId] {
case nil:
@@ -443,7 +449,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
thread: thread,
senderAci: senderAci
))
case .PAYMENT_ACTIVATION_REQUEST:
case .paymentActivationRequest:
let senderAci: Aci
switch context.recipientContext[chatItem.authorRecipientId] {
case nil:
@@ -461,7 +467,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
thread: thread,
senderAci: senderAci
))
case .UNSUPPORTED_PROTOCOL_MESSAGE:
case .unsupportedProtocolMessage:
let senderAddress: SignalServiceAddress?
switch context.recipientContext[chatItem.authorRecipientId] {
case nil:
@@ -483,7 +489,7 @@ final class MessageBackupSimpleChatUpdateArchiver {
// will always show "unknown protocol version", but that's fine.
protocolVersion: UInt(Int64.max)
))
case .REPORTED_SPAM:
case .reportedSpam:
simpleChatUpdateInteraction = .simpleInfoMessage(.reportedSpam)
}

View File

@@ -51,14 +51,15 @@ final class MessageBackupThreadMergeChatUpdateArchiver {
return messageFailure(.referencedRecipientIdMissing(.contact(mergedContactAddress)))
}
var chatUpdateMessage = BackupProto.ChatUpdateMessage()
chatUpdateMessage.update = .threadMerge(BackupProto.ThreadMergeChatUpdate(
previousE164: threadMergePhoneNumber.uint64Value
))
var threadMergeChatUpdate = BackupProto_ThreadMergeChatUpdate()
threadMergeChatUpdate.previousE164 = threadMergePhoneNumber.uint64Value
var chatUpdateMessage = BackupProto_ChatUpdateMessage()
chatUpdateMessage.update = .threadMerge(threadMergeChatUpdate)
let interactionArchiveDetails = Details(
author: threadRecipientId,
directionalDetails: .directionless(BackupProto.ChatItem.DirectionlessMessageDetails()),
directionalDetails: .directionless(BackupProto_ChatItem.DirectionlessMessageDetails()),
expireStartDate: nil,
expiresInMs: nil,
isSealedSender: false,
@@ -71,8 +72,8 @@ final class MessageBackupThreadMergeChatUpdateArchiver {
// MARK: -
func restoreThreadMergeChatUpdate(
_ threadMergeUpdateProto: BackupProto.ThreadMergeChatUpdate,
chatItem: BackupProto.ChatItem,
_ threadMergeUpdateProto: BackupProto_ThreadMergeChatUpdate,
chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: any DBWriteTransaction
@@ -89,7 +90,7 @@ final class MessageBackupThreadMergeChatUpdateArchiver {
}
guard let previousE164 = E164(threadMergeUpdateProto.previousE164) else {
return invalidProtoData(.invalidE164(protoClass: BackupProto.ThreadMergeChatUpdate.self))
return invalidProtoData(.invalidE164(protoClass: BackupProto_ThreadMergeChatUpdate.self))
}
guard case .contact(let mergedThread) = chatThread.threadType else {

View File

@@ -8,11 +8,11 @@ import LibSignalClient
public extension MessageBackup {
/// An identifier for a ``BackupProto.ChatItem`` backup frame.
/// An identifier for a ``BackupProto_ChatItem`` backup frame.
struct ChatItemId: MessageBackupLoggableId, Hashable {
let value: UInt64
public init(backupProtoChatItem: BackupProto.ChatItem) {
public init(backupProtoChatItem: BackupProto_ChatItem) {
self.value = backupProtoChatItem.dateSent
}
@@ -22,7 +22,7 @@ public extension MessageBackup {
// MARK: MessageBackupLoggableId
public var typeLogString: String { "BackupProto.ChatItem" }
public var typeLogString: String { "BackupProto_ChatItem" }
public var idLogString: String { "timestamp: \(value)" }
}
}
@@ -33,7 +33,7 @@ public protocol MessageBackupChatItemArchiver: MessageBackupProtoArchiver {
typealias ArchiveMultiFrameResult = MessageBackup.ArchiveMultiFrameResult<MessageBackup.InteractionUniqueId>
typealias RestoreFrameResult = MessageBackup.RestoreFrameResult<ChatItemId>
/// Archive all ``TSInteraction``s (they map to ``BackupProto.ChatItem`` and ``BackupProto.Call``).
/// Archive all ``TSInteraction``s (they map to ``BackupProto_ChatItem`` and ``BackupProto_Call``).
///
/// - Returns: ``ArchiveMultiFrameResult.success`` if all frames were written without error, or either
/// partial or complete failure otherwise.
@@ -47,13 +47,13 @@ public protocol MessageBackupChatItemArchiver: MessageBackupProtoArchiver {
tx: DBReadTransaction
) -> ArchiveMultiFrameResult
/// Restore a single ``BackupProto.ChatItem`` frame.
/// Restore a single ``BackupProto_ChatItem`` frame.
///
/// - Returns: ``RestoreFrameResult.success`` if all frames were read without error.
/// How to handle ``RestoreFrameResult.failure`` is up to the caller,
/// but typically an error will be shown to the user, but the restore will be allowed to proceed.
func restore(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult

View File

@@ -215,14 +215,13 @@ public class MessageBackupChatItemArchiverImpl: MessageBackupChatItemArchiver {
return .success
}
var chatItem = BackupProto.ChatItem(
chatId: chatId.value,
authorId: details.author.value,
dateSent: interaction.timestamp,
expireStartDate: details.expireStartDate ?? 0,
expiresInMs: details.expiresInMs ?? 0,
sms: details.isSms
)
var chatItem = BackupProto_ChatItem()
chatItem.chatID = chatId.value
chatItem.authorID = details.author.value
chatItem.dateSent = interaction.timestamp
chatItem.expireStartDate = details.expireStartDate ?? 0
chatItem.expiresInMs = details.expiresInMs ?? 0
chatItem.sms = details.isSms
chatItem.item = details.chatItemType
chatItem.directionalDetails = details.directionalDetails
chatItem.revisions = details.revisions
@@ -231,7 +230,7 @@ public class MessageBackupChatItemArchiverImpl: MessageBackupChatItemArchiver {
stream,
objectId: interaction.uniqueInteractionId
) {
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .chatItem(chatItem)
return frame
}
@@ -247,7 +246,7 @@ public class MessageBackupChatItemArchiverImpl: MessageBackupChatItemArchiver {
}
public func restore(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult {

View File

@@ -20,15 +20,15 @@ extension MessageBackup {
}
struct InteractionArchiveDetails {
typealias DirectionalDetails = BackupProto.ChatItem.DirectionalDetails
typealias ChatItemType = BackupProto.ChatItem.Item
typealias DirectionalDetails = BackupProto_ChatItem.OneOf_DirectionalDetails
typealias ChatItemType = BackupProto_ChatItem.OneOf_Item
let author: RecipientId
let directionalDetails: DirectionalDetails
let expireStartDate: UInt64?
let expiresInMs: UInt64?
// TODO: [Backups] Include edit revisions.
let revisions: [BackupProto.ChatItem] = []
let revisions: [BackupProto_ChatItem] = []
// TODO: [Backups] Properly set isSms. This will only be relevant for messages we previously restored from an Android.
let isSms: Bool = false
let isSealedSender: Bool
@@ -166,7 +166,7 @@ internal protocol MessageBackupInteractionArchiver: MessageBackupProtoArchiver {
) -> MessageBackup.ArchiveInteractionResult<Details>
func restoreChatItem(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
@@ -301,7 +301,7 @@ extension MessageBackup.RestoreInteractionResult where Component == Void {
}
}
extension BackupProto.ChatItem {
extension BackupProto_ChatItem {
var id: MessageBackup.ChatItemId {
return .init(backupProtoChatItem: self)

View File

@@ -21,11 +21,11 @@ internal class MessageBackupReactionArchiver: MessageBackupProtoArchiver {
_ message: TSMessage,
context: MessageBackup.RecipientArchivingContext,
tx: DBReadTransaction
) -> MessageBackup.ArchiveInteractionResult<[BackupProto.Reaction]> {
) -> MessageBackup.ArchiveInteractionResult<[BackupProto_Reaction]> {
let reactions = reactionStore.allReactions(messageId: message.uniqueId, tx: tx)
var errors = [ArchiveFrameError]()
var reactionProtos = [BackupProto.Reaction]()
var reactionProtos = [BackupProto_Reaction]()
for reaction in reactions {
guard
@@ -47,14 +47,13 @@ internal class MessageBackupReactionArchiver: MessageBackupProtoArchiver {
continue
}
let reaction = BackupProto.Reaction(
emoji: reaction.emoji,
authorId: authorId.value,
sentTimestamp: reaction.sentAtTimestamp,
sortOrder: reaction.sortOrder
)
var reactionProto = BackupProto_Reaction()
reactionProto.emoji = reaction.emoji
reactionProto.authorID = authorId.value
reactionProto.sentTimestamp = reaction.sentAtTimestamp
reactionProto.sortOrder = reaction.sortOrder
reactionProtos.append(reaction)
reactionProtos.append(reactionProto)
}
if errors.isEmpty {
@@ -67,7 +66,7 @@ internal class MessageBackupReactionArchiver: MessageBackupProtoArchiver {
// MARK: Restoring
func restoreReactions(
_ reactions: [BackupProto.Reaction],
_ reactions: [BackupProto_Reaction],
chatItemId: MessageBackup.ChatItemId,
message: TSMessage,
context: MessageBackup.RecipientRestoringContext,

View File

@@ -93,12 +93,11 @@ internal class MessageBackupTSIncomingMessageArchiver: MessageBackupInteractionA
private func buildIncomingMessageDetails(
_ message: TSIncomingMessage
) -> MessageBackup.ArchiveInteractionResult<Details.DirectionalDetails> {
let incomingMessage = BackupProto.ChatItem.IncomingMessageDetails(
dateReceived: message.receivedAtTimestamp,
dateServerSent: message.serverDeliveryTimestamp,
read: message.wasRead,
sealedSender: message.wasReceivedByUD
)
var incomingMessage = BackupProto_ChatItem.IncomingMessageDetails()
incomingMessage.dateReceived = message.receivedAtTimestamp
incomingMessage.dateServerSent = message.serverDeliveryTimestamp
incomingMessage.read = message.wasRead
incomingMessage.sealedSender = message.wasReceivedByUD
return .success(.incoming(incomingMessage))
}
@@ -106,12 +105,12 @@ internal class MessageBackupTSIncomingMessageArchiver: MessageBackupInteractionA
// MARK: - Restoring
func restoreChatItem(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> MessageBackup.RestoreInteractionResult<Void> {
let incomingDetails: BackupProto.ChatItem.IncomingMessageDetails
let incomingDetails: BackupProto_ChatItem.IncomingMessageDetails
switch chatItem.directionalDetails {
case .incoming(let incomingMessageDetails):
incomingDetails = incomingMessageDetails

View File

@@ -28,13 +28,13 @@ extension MessageBackup {
// construct objects that are parsed from the backup proto but require
// the TSMessage to exist first before they can be created/inserted.
fileprivate let reactions: [BackupProto.Reaction]
fileprivate let reactions: [BackupProto_Reaction]
}
struct Payment {
enum Status {
case success(BackupProto.PaymentNotification.TransactionDetails.Transaction.Status)
case failure(BackupProto.PaymentNotification.TransactionDetails.FailedTransaction.FailureReason)
case success(BackupProto_PaymentNotification.TransactionDetails.Transaction.Status)
case failure(BackupProto_PaymentNotification.TransactionDetails.FailedTransaction.FailureReason)
}
let amount: String?
@@ -42,7 +42,7 @@ extension MessageBackup {
let note: String?
fileprivate let status: Status
fileprivate let payment: BackupProto.PaymentNotification.TransactionDetails.Transaction?
fileprivate let payment: BackupProto_PaymentNotification.TransactionDetails.Transaction?
}
case text(Text)
@@ -135,12 +135,12 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
context: MessageBackup.RecipientArchivingContext,
tx: DBReadTransaction
) -> ArchiveInteractionResult<ChatItemType> {
var standardMessage = BackupProto.StandardMessage()
var standardMessage = BackupProto_StandardMessage()
var partialErrors = [ArchiveFrameError]()
let text: BackupProto.Text
let text: BackupProto_Text
let textResult = archiveText(
.init(text: messageBody, ranges: message.bodyRanges ?? .empty),
MessageBody(text: messageBody, ranges: message.bodyRanges ?? .empty),
interactionUniqueId: message.uniqueInteractionId
)
switch textResult.bubbleUp(ChatItemType.self, partialErrors: &partialErrors) {
@@ -151,25 +151,24 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
standardMessage.text = text
let quote: BackupProto.Quote?
if let quotedMessage = message.quotedMessage {
let quote: BackupProto_Quote
let quoteResult = archiveQuote(
quotedMessage,
interactionUniqueId: message.uniqueInteractionId,
context: context
)
switch quoteResult.bubbleUp(ChatItemType.self, partialErrors: &partialErrors) {
case .continue(let value):
quote = value
case .continue(let _quote):
quote = _quote
case .bubbleUpError(let errorResult):
return errorResult
}
} else {
quote = nil
}
standardMessage.quote = quote
let reactions: [BackupProto.Reaction]
standardMessage.quote = quote
}
let reactions: [BackupProto_Reaction]
let reactionsResult = reactionArchiver.archiveReactions(
message,
context: context,
@@ -200,10 +199,16 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
return .messageFailure([.archiveFrameError(.missingPaymentInformation, uniqueInteractionId)])
}
var paymentNotificationProto = BackupProto.PaymentNotification()
paymentNotificationProto.amountMob = archivedPaymentMessage.archivedPaymentInfo.amount
paymentNotificationProto.feeMob = archivedPaymentMessage.archivedPaymentInfo.fee
paymentNotificationProto.note = archivedPaymentMessage.archivedPaymentInfo.note
var paymentNotificationProto = BackupProto_PaymentNotification()
if let amount = archivedPaymentMessage.archivedPaymentInfo.amount {
paymentNotificationProto.amountMob = amount
}
if let fee = archivedPaymentMessage.archivedPaymentInfo.fee {
paymentNotificationProto.feeMob = fee
}
if let note = archivedPaymentMessage.archivedPaymentInfo.note {
paymentNotificationProto.note = note
}
paymentNotificationProto.transactionDetails = historyItem.toTransactionDetailsProto()
return .success(.paymentNotification(paymentNotificationProto))
@@ -225,21 +230,29 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
return .messageFailure([.archiveFrameError(.missingPaymentInformation, uniqueInteractionId)])
}
var paymentNotificationProto = BackupProto.PaymentNotification()
var paymentNotificationProto = BackupProto_PaymentNotification()
if let amount = model.paymentAmount {
paymentNotificationProto.amountMob = PaymentsFormat.format(
if
let amount = model.paymentAmount,
let amountString = PaymentsFormat.format(
picoMob: amount.picoMob,
isShortForm: true
)
{
paymentNotificationProto.amountMob = amountString
}
if let fee = model.mobileCoin?.feeAmount {
paymentNotificationProto.feeMob = PaymentsFormat.format(
if
let fee = model.mobileCoin?.feeAmount,
let feeString = PaymentsFormat.format(
picoMob: fee.picoMob,
isShortForm: true
)
{
paymentNotificationProto.feeMob = feeString
}
if let memoMessage = paymentNotification.memoMessage {
paymentNotificationProto.note = memoMessage
}
paymentNotificationProto.note = paymentNotification.memoMessage
paymentNotificationProto.transactionDetails = model.asArchivedPayment().toTransactionDetailsProto()
return .success(.paymentNotification(paymentNotificationProto))
@@ -248,11 +261,12 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
private func archiveText(
_ messageBody: MessageBody,
interactionUniqueId: MessageBackup.InteractionUniqueId
) -> ArchiveInteractionResult<BackupProto.Text> {
var text = BackupProto.Text(body: messageBody.text)
) -> ArchiveInteractionResult<BackupProto_Text> {
var text = BackupProto_Text()
text.body = messageBody.text
for bodyRangeParam in messageBody.ranges.toProtoBodyRanges() {
var bodyRange = BackupProto.BodyRange()
var bodyRange = BackupProto_BodyRange()
bodyRange.start = bodyRangeParam.start
bodyRange.length = bodyRangeParam.length
@@ -261,14 +275,14 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
mentionAci.serviceIdBinary.asData
)
} else if let style = bodyRangeParam.style {
let backupProtoStyle: BackupProto.BodyRange.Style = {
let backupProtoStyle: BackupProto_BodyRange.Style = {
switch style {
case .none: return .NONE
case .bold: return .BOLD
case .italic: return .ITALIC
case .spoiler: return .SPOILER
case .strikethrough: return .STRIKETHROUGH
case .monospace: return .MONOSPACE
case .none: return .none
case .bold: return .bold
case .italic: return .italic
case .spoiler: return .spoiler
case .strikethrough: return .strikethrough
case .monospace: return .monospace
}
}()
@@ -285,7 +299,7 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
_ quotedMessage: TSQuotedMessage,
interactionUniqueId: MessageBackup.InteractionUniqueId,
context: MessageBackup.RecipientArchivingContext
) -> ArchiveInteractionResult<BackupProto.Quote> {
) -> ArchiveInteractionResult<BackupProto_Quote> {
var partialErrors = [ArchiveFrameError]()
guard let authorAddress = quotedMessage.authorAddress.asSingleServiceIdBackupAddress() else {
@@ -300,19 +314,20 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
)])
}
var quote = BackupProto.Quote(
authorId: authorId.value,
type: quotedMessage.isGiftBadge ? .GIFTBADGE : .NORMAL
)
quote.targetSentTimestamp = quotedMessage.timestampValue?.uint64Value
var quote = BackupProto_Quote()
quote.authorID = authorId.value
quote.type = quotedMessage.isGiftBadge ? .giftbadge : .normal
if let targetSentTimestamp = quotedMessage.timestampValue?.uint64Value {
quote.targetSentTimestamp = targetSentTimestamp
}
if let body = quotedMessage.body {
let textResult = archiveText(
.init(text: body, ranges: quotedMessage.bodyRanges ?? .empty),
MessageBody(text: body, ranges: quotedMessage.bodyRanges ?? .empty),
interactionUniqueId: interactionUniqueId
)
let text: BackupProto.Text
switch textResult.bubbleUp(BackupProto.Quote.self, partialErrors: &partialErrors) {
let text: BackupProto_Text
switch textResult.bubbleUp(BackupProto_Quote.self, partialErrors: &partialErrors) {
case .continue(let value):
text = value
case .bubbleUpError(let errorResult):
@@ -457,28 +472,33 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
private func restorePaymentNotification(
_ paymentNotification: BackupProto.PaymentNotification,
_ paymentNotification: BackupProto_PaymentNotification,
chatItemId: MessageBackup.ChatItemId,
thread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBReadTransaction
) -> RestoreInteractionResult<MessageBackup.RestoredMessageContents> {
let status: MessageBackup.RestoredMessageContents.Payment.Status
let paymentTransaction: BackupProto.PaymentNotification.TransactionDetails.Transaction?
switch paymentNotification.transactionDetails?.payment {
case .failedTransaction(let failedTransaction):
status = .failure(failedTransaction.reason)
paymentTransaction = nil
case .transaction(let payment):
status = .success(payment.status)
paymentTransaction = payment
case .none:
let paymentTransaction: BackupProto_PaymentNotification.TransactionDetails.Transaction?
if
paymentNotification.hasTransactionDetails,
let paymentDetails = paymentNotification.transactionDetails.payment
{
switch paymentDetails {
case .failedTransaction(let failedTransaction):
status = .failure(failedTransaction.reason)
paymentTransaction = nil
case .transaction(let payment):
status = .success(payment.status)
paymentTransaction = payment
}
} else {
// Default to 'success' if there is no included information
status = .success(.SUCCESSFUL)
status = .success(.successful)
paymentTransaction = nil
}
return .success(.archivedPayment(.init(
return .success(.archivedPayment(MessageBackup.RestoredMessageContents.Payment(
amount: paymentNotification.amountMob,
fee: paymentNotification.feeMob,
note: paymentNotification.note,
@@ -488,7 +508,7 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
private func restoreStandardMessage(
_ standardMessage: BackupProto.StandardMessage,
_ standardMessage: BackupProto_StandardMessage,
chatItemId: MessageBackup.ChatItemId,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
@@ -497,10 +517,10 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
var partialErrors = [RestoreFrameError]()
let quotedMessage: TSQuotedMessage?
if let quoteProto = standardMessage.quote {
if standardMessage.hasQuote {
guard
let quoteResult = restoreQuote(
quoteProto,
standardMessage.quote,
chatItemId: chatItemId,
thread: chatThread,
context: context,
@@ -514,10 +534,11 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
quotedMessage = nil
}
guard let text = standardMessage.text else {
guard standardMessage.hasText else {
// TODO: [Backups] Support messages with no text
return .messageFailure([.restoreFrameError(.unimplemented, chatItemId)])
}
let text = standardMessage.text
let messageBodyResult = restoreMessageBody(text, chatItemId: chatItemId)
switch messageBodyResult {
@@ -542,7 +563,7 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
func restoreMessageBody(
_ text: BackupProto.Text,
_ text: BackupProto_Text,
chatItemId: MessageBackup.ChatItemId
) -> RestoreInteractionResult<MessageBody> {
return restoreMessageBody(
@@ -554,23 +575,25 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
private func restoreMessageBody(
text: String,
bodyRangeProtos: [BackupProto.BodyRange],
bodyRangeProtos: [BackupProto_BodyRange],
chatItemId: MessageBackup.ChatItemId
) -> RestoreInteractionResult<MessageBody> {
var partialErrors = [RestoreFrameError]()
var bodyMentions = [NSRange: Aci]()
var bodyStyles = [NSRangedValue<MessageBodyRanges.SingleStyle>]()
for bodyRange in bodyRangeProtos {
guard let bodyRangeStart = bodyRange.start, let bodyRangeLength = bodyRange.length else {
guard bodyRange.hasStart, bodyRange.hasLength else {
continue
}
let bodyRangeStart = bodyRange.start
let bodyRangeLength = bodyRange.length
let range = NSRange(location: Int(bodyRangeStart), length: Int(bodyRangeLength))
switch bodyRange.associatedValue {
case .mentionAci(let aciData):
guard let mentionAci = try? Aci.parseFrom(serviceIdBinary: aciData) else {
partialErrors.append(.restoreFrameError(
.invalidProtoData(.invalidAci(protoClass: BackupProto.BodyRange.self)),
.invalidProtoData(.invalidAci(protoClass: BackupProto_BodyRange.self)),
chatItemId
))
continue
@@ -579,27 +602,27 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
case .style(let protoBodyRangeStyle):
let swiftStyle: MessageBodyRanges.SingleStyle
switch protoBodyRangeStyle {
case .NONE:
case .none, .UNRECOGNIZED:
partialErrors.append(.restoreFrameError(
.invalidProtoData(.unrecognizedBodyRangeStyle),
chatItemId
))
continue
case .BOLD:
case .bold:
swiftStyle = .bold
case .ITALIC:
case .italic:
swiftStyle = .italic
case .MONOSPACE:
case .monospace:
swiftStyle = .monospace
case .SPOILER:
case .spoiler:
swiftStyle = .spoiler
case .STRIKETHROUGH:
case .strikethrough:
swiftStyle = .strikethrough
}
bodyStyles.append(.init(swiftStyle, range: range))
case nil:
partialErrors.append(.restoreFrameError(
.invalidProtoData(.invalidAci(protoClass: BackupProto.BodyRange.self)),
.invalidProtoData(.invalidAci(protoClass: BackupProto_BodyRange.self)),
chatItemId
))
continue
@@ -618,7 +641,7 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
private func restoreQuote(
_ quote: BackupProto.Quote,
_ quote: BackupProto_Quote,
chatItemId: MessageBackup.ChatItemId,
thread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
@@ -653,10 +676,10 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
let targetMessageTimestamp: NSNumber?
if
let targetSentTimestamp = quote.targetSentTimestamp,
SDS.fitsInInt64(targetSentTimestamp)
quote.hasTargetSentTimestamp,
SDS.fitsInInt64(quote.targetSentTimestamp)
{
targetMessageTimestamp = NSNumber(value: targetSentTimestamp)
targetMessageTimestamp = NSNumber(value: quote.targetSentTimestamp)
} else {
targetMessageTimestamp = nil
}
@@ -679,9 +702,9 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
} else {
bodySource = .remote
if let text = quote.text {
if quote.hasText {
guard let bodyResult = restoreMessageBody(
text: text,
text: quote.text,
bodyRangeProtos: quote.bodyRanges,
chatItemId: chatItemId
)
@@ -697,9 +720,9 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
let isGiftBadge: Bool
switch quote.type {
case .UNKNOWN, .NORMAL:
case .UNRECOGNIZED, .unknown, .normal:
isGiftBadge = false
case .GIFTBADGE:
case .giftbadge:
isGiftBadge = true
}
@@ -727,16 +750,18 @@ internal class MessageBackupTSMessageContentsArchiver: MessageBackupProtoArchive
}
private func findTargetMessageForQuote(
quote: BackupProto.Quote,
quote: BackupProto_Quote,
thread: MessageBackup.ChatThread,
tx: DBReadTransaction
) -> TSMessage? {
guard let targetSentTimestamp = quote.targetSentTimestamp else {
return nil
}
guard
quote.hasTargetSentTimestamp,
SDS.fitsInInt64(quote.targetSentTimestamp)
else { return nil }
let messageCandidates: [TSInteraction] = (try? interactionStore
.interactions(
withTimestamp: targetSentTimestamp,
withTimestamp: quote.targetSentTimestamp,
tx: tx
)
) ?? []
@@ -784,7 +809,7 @@ fileprivate extension ArchivedPayment {
)
case .success(let status):
let payment = backup.payment
let transactionIdentifier = payment?.mobileCoinIdentification?.nilIfEmpty.map {
let transactionIdentifier = payment?.mobileCoinIdentification.nilIfEmpty.map {
TransactionIdentifier(publicKey: $0.publicKey, keyImages: $0.keyImages)
}
@@ -809,27 +834,27 @@ fileprivate extension ArchivedPayment {
}
}
extension BackupProto.PaymentNotification.TransactionDetails.FailedTransaction.FailureReason {
extension BackupProto_PaymentNotification.TransactionDetails.FailedTransaction.FailureReason {
func asFailureType() -> ArchivedPayment.FailureReason {
switch self {
case .GENERIC: return .genericFailure
case .NETWORK: return .networkFailure
case .INSUFFICIENT_FUNDS: return .insufficientFundsFailure
case .UNRECOGNIZED, .generic: return .genericFailure
case .network: return .networkFailure
case .insufficientFunds: return .insufficientFundsFailure
}
}
}
extension BackupProto.PaymentNotification.TransactionDetails.Transaction.Status {
extension BackupProto_PaymentNotification.TransactionDetails.Transaction.Status {
func asStatusType() -> ArchivedPayment.Status {
switch self {
case .INITIAL: return .initial
case .SUBMITTED: return .submitted
case .SUCCESSFUL: return .successful
case .UNRECOGNIZED, .initial: return .initial
case .submitted: return .submitted
case .successful: return .successful
}
}
}
extension BackupProto.PaymentNotification.TransactionDetails.MobileCoinTxoIdentification {
extension BackupProto_PaymentNotification.TransactionDetails.MobileCoinTxoIdentification {
var nilIfEmpty: Self? {
(publicKey.isEmpty && keyImages.isEmpty) ? nil : self
}

View File

@@ -93,7 +93,7 @@ internal class MessageBackupTSOutgoingMessageArchiver: MessageBackupInteractionA
var perRecipientErrors = [ArchiveFrameError]()
var wasAnySendSealedSender = false
var outgoingMessage = BackupProto.ChatItem.OutgoingMessageDetails()
var outgoingMessage = BackupProto_ChatItem.OutgoingMessageDetails()
for (address, sendState) in message.recipientAddressStates ?? [:] {
guard let recipientAddress = address.asSingleServiceIdBackupAddress()?.asArchivingAddress() else {
@@ -112,45 +112,45 @@ internal class MessageBackupTSOutgoingMessageArchiver: MessageBackupInteractionA
}
var isNetworkFailure = false
var isIdentityKeyMismatchFailure = false
let protoDeliveryStatus: BackupProto.SendStatus.Status
let protoDeliveryStatus: BackupProto_SendStatus.Status
let statusTimestamp: UInt64
switch sendState.state {
case OWSOutgoingMessageRecipientState.sent:
if let readTimestamp = sendState.readTimestamp {
protoDeliveryStatus = .READ
protoDeliveryStatus = .read
statusTimestamp = readTimestamp.uint64Value
} else if let viewedTimestamp = sendState.viewedTimestamp {
protoDeliveryStatus = .VIEWED
protoDeliveryStatus = .viewed
statusTimestamp = viewedTimestamp.uint64Value
} else if let deliveryTimestamp = sendState.deliveryTimestamp {
protoDeliveryStatus = .DELIVERED
protoDeliveryStatus = .delivered
statusTimestamp = deliveryTimestamp.uint64Value
} else {
protoDeliveryStatus = .SENT
protoDeliveryStatus = .sent
statusTimestamp = message.timestamp
}
case OWSOutgoingMessageRecipientState.failed:
// TODO: [Backups] Identify specific errors (see recipientState.errorCode). For now, call everything network.
isNetworkFailure = true
isIdentityKeyMismatchFailure = false
protoDeliveryStatus = .FAILED
protoDeliveryStatus = .failed
statusTimestamp = message.timestamp
case OWSOutgoingMessageRecipientState.sending, OWSOutgoingMessageRecipientState.pending:
protoDeliveryStatus = .PENDING
protoDeliveryStatus = .pending
statusTimestamp = message.timestamp
case OWSOutgoingMessageRecipientState.skipped:
protoDeliveryStatus = .SKIPPED
protoDeliveryStatus = .skipped
statusTimestamp = message.timestamp
}
let sendStatus = BackupProto.SendStatus(
recipientId: recipientId.value,
deliveryStatus: protoDeliveryStatus,
networkFailure: isNetworkFailure,
identityKeyMismatch: isIdentityKeyMismatchFailure,
sealedSender: sendState.wasSentByUD.negated,
lastStatusUpdateTimestamp: statusTimestamp
)
var sendStatus = BackupProto_SendStatus()
sendStatus.recipientID = recipientId.value
sendStatus.deliveryStatus = protoDeliveryStatus
sendStatus.networkFailure = isNetworkFailure
sendStatus.identityKeyMismatch = isIdentityKeyMismatchFailure
// TODO: [Backups] Is this check inverted?
sendStatus.sealedSender = sendState.wasSentByUD.negated
sendStatus.lastStatusUpdateTimestamp = statusTimestamp
outgoingMessage.sendStatus.append(sendStatus)
@@ -160,13 +160,13 @@ internal class MessageBackupTSOutgoingMessageArchiver: MessageBackupInteractionA
}
if perRecipientErrors.isEmpty {
return .success(.init(
return .success(OutgoingMessageDetails(
details: .outgoing(outgoingMessage),
wasAnySendSealedSender: wasAnySendSealedSender
))
} else {
return .partialFailure(
.init(
OutgoingMessageDetails(
details: .outgoing(outgoingMessage),
wasAnySendSealedSender: wasAnySendSealedSender
),
@@ -178,12 +178,12 @@ internal class MessageBackupTSOutgoingMessageArchiver: MessageBackupInteractionA
// MARK: - Restoring
func restoreChatItem(
_ chatItem: BackupProto.ChatItem,
_ chatItem: BackupProto_ChatItem,
chatThread: MessageBackup.ChatThread,
context: MessageBackup.ChatRestoringContext,
tx: DBWriteTransaction
) -> MessageBackup.RestoreInteractionResult<Void> {
let outgoingDetails: BackupProto.ChatItem.OutgoingMessageDetails
let outgoingDetails: BackupProto_ChatItem.OutgoingMessageDetails
switch chatItem.directionalDetails {
case .outgoing(let backupProtoChatItemOutgoingMessageDetails):
outgoingDetails = backupProtoChatItemOutgoingMessageDetails

View File

@@ -11,7 +11,7 @@ import LibSignalClient
///
/// So we represent restored messages as "transcripts" that we can plug into the same
/// transcript processing pipes as synced message transcripts.
internal class RestoredSentMessageTranscript: SentMessageTranscript {
class RestoredSentMessageTranscript: SentMessageTranscript {
let type: SentMessageTranscriptType
@@ -22,10 +22,10 @@ internal class RestoredSentMessageTranscript: SentMessageTranscript {
let recipientStates: [MessageBackup.InteropAddress: TSOutgoingMessageRecipientState]
internal static func from(
chatItem: BackupProto.ChatItem,
static func from(
chatItem: BackupProto_ChatItem,
contents: MessageBackup.RestoredMessageContents,
outgoingDetails: BackupProto.ChatItem.OutgoingMessageDetails,
outgoingDetails: BackupProto_ChatItem.OutgoingMessageDetails,
context: MessageBackup.ChatRestoringContext,
chatThread: MessageBackup.ChatThread
) -> MessageBackup.RestoreInteractionResult<RestoredSentMessageTranscript> {
@@ -117,7 +117,7 @@ internal class RestoredSentMessageTranscript: SentMessageTranscript {
private static func restoreMessageTranscript(
contents: MessageBackup.RestoredMessageContents.Text,
target: SentMessageTranscriptTarget,
chatItem: BackupProto.ChatItem,
chatItem: BackupProto_ChatItem,
expirationToken: DisappearingMessageToken
) -> SentMessageTranscriptType {
let messageParams = SentMessageTranscriptType.Message(
@@ -155,7 +155,7 @@ internal class RestoredSentMessageTranscript: SentMessageTranscript {
private static func restorePaymentTranscript(
payment: MessageBackup.RestoredMessageContents.Payment,
target: SentMessageTranscriptTarget,
chatItem: BackupProto.ChatItem,
chatItem: BackupProto_ChatItem,
expirationToken: DisappearingMessageToken
) -> SentMessageTranscriptType {
return .archivedPayment(
@@ -171,7 +171,7 @@ internal class RestoredSentMessageTranscript: SentMessageTranscript {
}
private static func recipientState(
for sendStatus: BackupProto.SendStatus,
for sendStatus: BackupProto_SendStatus,
partialErrors: inout [MessageBackup.RestoreFrameError<MessageBackup.ChatItemId>],
chatItemId: MessageBackup.ChatItemId
) -> TSOutgoingMessageRecipientState? {
@@ -186,37 +186,37 @@ internal class RestoredSentMessageTranscript: SentMessageTranscript {
recipientState.wasSentByUD = sendStatus.sealedSender.negated
switch sendStatus.deliveryStatus {
case .UNKNOWN:
case .unknown, .UNRECOGNIZED:
partialErrors.append(.restoreFrameError(.invalidProtoData(.unrecognizedMessageSendStatus), chatItemId))
return nil
case .PENDING:
case .pending:
recipientState.state = .pending
recipientState.errorCode = nil
return recipientState
case .SENT:
case .sent:
recipientState.state = .sent
recipientState.errorCode = nil
return recipientState
case .DELIVERED:
case .delivered:
recipientState.state = .sent
recipientState.deliveryTimestamp = NSNumber(value: sendStatus.lastStatusUpdateTimestamp)
recipientState.errorCode = nil
return recipientState
case .READ:
case .read:
recipientState.state = .sent
recipientState.readTimestamp = NSNumber(value: sendStatus.lastStatusUpdateTimestamp)
recipientState.errorCode = nil
return recipientState
case .VIEWED:
case .viewed:
recipientState.state = .sent
recipientState.viewedTimestamp = NSNumber(value: sendStatus.lastStatusUpdateTimestamp)
recipientState.errorCode = nil
return recipientState
case .SKIPPED:
case .skipped:
recipientState.state = .skipped
recipientState.errorCode = nil
return recipientState
case .FAILED:
case .failed:
recipientState.state = .failed
if sendStatus.identityKeyMismatch {
// We want to explicitly represent identity key errors.

View File

@@ -332,22 +332,22 @@ extension MessageBackup {
/// A message must come from either an Aci or an E164.
/// One in the backup did not.
case incomingMessageNotFromAciOrE164
/// Outgoing message's BackupProto.SendStatus can only be for BackupProto.Contacts.
/// Outgoing message's `BackupProto_SendStatus` can only be for `BackupProto_Contacts`.
/// One in the backup was to a group, self recipient, or something else.
case outgoingNonContactMessageRecipient
/// A BackupProto.SendStatus had an unregonized BackupProto.SendStatusStatus.
/// A `BackupProto_SendStatus` had an unregonized `BackupProto_SendStatusStatus`.
case unrecognizedMessageSendStatus
/// BackupProto.Reaction must come from either an Aci or an E164.
/// `BackupProto_Reaction` must come from either an Aci or an E164.
/// One in the backup did not.
case reactionNotFromAciOrE164
/// A BackupProto.BodyRange with a missing or unrecognized style.
/// A `BackupProto_BodyRange` with a missing or unrecognized style.
case unrecognizedBodyRangeStyle
/// A BackupProto.Group's gv2 master key could not be parsed by libsignal.
/// A `BackupProto_Group's` gv2 master key could not be parsed by libsignal.
case invalidGV2MasterKey
/// A BackupProtoGroup was missing its group snapshot.
/// A `BackupProto_Group` was missing its group snapshot.
case missingGV2GroupSnapshot
/// A ``BackupProtoGroup/BackupProtoFullGroupMember/role`` was
/// unrecognized. Includes the class of the offending proto.
@@ -358,14 +358,14 @@ extension MessageBackup {
/// We failed to build a V2 group model while restoring a group.
case failedToBuildGV2GroupModel
/// A BackupProto.GroupChangeChatUpdate ChatItem with a non-group-chat chatId.
/// A `BackupProto_GroupChangeChatUpdate` ChatItem with a non-group-chat chatId.
case groupUpdateMessageInNonGroupChat
/// A BackupProto.GroupChangeChatUpdate ChatItem without any updates!
/// A `BackupProto_GroupChangeChatUpdate` ChatItem without any updates!
case emptyGroupUpdates
/// A BackupProto.GroupSequenceOfRequestsAndCancelsUpdate where
/// A `BackupProto_GroupSequenceOfRequestsAndCancelsUpdate` where
/// the requester is the local user, which isn't allowed.
case sequenceOfRequestsAndCancelsWithLocalAci
/// An unrecognized BackupProto.GroupChangeChatUpdate.
/// An unrecognized `BackupProto_GroupChangeChatUpdate`.
case unrecognizedGroupUpdate
/// A frame was entirely missing its enclosed item.
@@ -376,34 +376,34 @@ extension MessageBackup {
/// A profile key for the local user that could not be parsed into a valid aes256 key
case invalidLocalUsernameLink
/// A BackupProto.IndividualCall chat item update was associated
/// A `BackupProto_IndividualCall` chat item update was associated
/// with a thread that was not a contact thread.
case individualCallNotInContactThread
/// A BackupProto.IndividualCall had an unrecognized type.
/// A `BackupProto_IndividualCall` had an unrecognized type.
case individualCallUnrecognizedType
/// A BackupProto.IndividualCall had an unrecognized direction.
/// A `BackupProto_IndividualCall` had an unrecognized direction.
case individualCallUnrecognizedDirection
/// A BackupProto.IndividualCall had an unrecognized state.
/// A `BackupProto_IndividualCall` had an unrecognized state.
case individualCallUnrecognizedState
/// A BackupProto.GroupCall chat item update was associated with
/// A `BackupProto_GroupCall` chat item update was associated with
/// a thread that was not a group thread.
case groupCallNotInGroupThread
/// A BackupProto.GroupCall had an unrecognized state.
/// A `BackupProto_GroupCall` had an unrecognized state.
case groupCallUnrecognizedState
/// A BackupProto.GroupCall referenced a recipient that was not
/// A `BackupProto_GroupCall` referenced a recipient that was not
/// a contact or otherwise did not contain an ACI.
case groupCallRecipientIdNotAnAci(RecipientId)
/// BackupProto.DistributionListItem was missing its item
/// `BackupProto_DistributionListItem` was missing its item
case distributionListItemMissingItem
/// BackupProto.DistributionList.distributionId was not a valid UUID
/// `BackupProto_DistributionList.distributionId` was not a valid UUID
case invalidDistributionListId
/// BackupProto.DistributionList.privacyMode was missing, or contained an unknown privacy mode
/// `BackupProto_DistributionList.privacyMode` was missing, or contained an unknown privacy mode
case invalidDistributionListPrivacyMode
/// The specified BackupProto.DistributionList.privacyMode was missing a list of associated member IDs
/// The specified `BackupProto_DistributionList.privacyMode` was missing a list of associated member IDs
case invalidDistributionListPrivacyModeMissingRequiredMembers
/// BackupProto.DistributionListItem.deletionTimestamp was invalid
/// `BackupProto_DistributionListItem.deletionTimestamp` was invalid
case invalidDistributionListDeletionTimestamp
/// A ``BackupProto/ChatUpdateMessage/update`` was empty.

View File

@@ -63,7 +63,7 @@ extension MessageBackupProtoArchiver {
internal static func writeFrameToStream<AppIdType>(
_ stream: MessageBackupProtoOutputStream,
objectId: AppIdType,
frameBuilder: () -> BackupProto.Frame
frameBuilder: () -> BackupProto_Frame
) -> MessageBackup.ArchiveFrameError<AppIdType>? {
let frame = frameBuilder()
switch stream.writeFrame(frame) {

View File

@@ -6,7 +6,7 @@
import Foundation
import LibSignalClient
/// Archives ``SignalRecipient``s as ``BackupProto.Contact`` recipients.
/// Archives ``SignalRecipient``s as ``BackupProto_Contact`` recipients.
public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
typealias RecipientId = MessageBackup.RecipientId
typealias RecipientAppId = MessageBackup.RecipientArchivingContext.Address
@@ -90,63 +90,72 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
let storyContext = recipient.aci.map { self.storyStore.getOrCreateStoryContextAssociatedData(for: $0, tx: tx) }
var contact = BackupProto.Contact(
blocked: blockedAddresses.contains(recipient.address),
visibility: { () -> BackupProto.Contact.Visibility in
if self.recipientHidingManager.isHiddenRecipient(recipient, tx: tx) {
if
let contactThread = threadStore.fetchContactThread(recipient: recipient, tx: tx),
threadStore.hasPendingMessageRequest(thread: contactThread, tx: tx)
{
return .HIDDEN_MESSAGE_REQUEST
}
return .HIDDEN
} else {
return .VISIBLE
var contact = BackupProto_Contact()
contact.blocked = blockedAddresses.contains(recipient.address)
contact.visibility = { () -> BackupProto_Contact.Visibility in
if self.recipientHidingManager.isHiddenRecipient(recipient, tx: tx) {
if
let contactThread = threadStore.fetchContactThread(recipient: recipient, tx: tx),
threadStore.hasPendingMessageRequest(thread: contactThread, tx: tx)
{
return .hiddenMessageRequest
}
}(),
profileSharing: whitelistedAddresses.contains(recipient.address),
hideStory: storyContext?.isHidden ?? false
)
contact.registration = { () -> BackupProto.Contact.Registration in
if !recipient.isRegistered {
let unregisteredAtTimestamp = recipient.unregisteredAtTimestamp ?? SignalRecipient.Constants.distantPastUnregisteredTimestamp
return .notRegistered(BackupProto.Contact.NotRegistered(
unregisteredTimestamp: unregisteredAtTimestamp
))
return .hidden
} else {
return .visible
}
}()
contact.profileSharing = whitelistedAddresses.contains(recipient.address)
contact.hideStory = storyContext?.isHidden ?? false
contact.registration = { () -> BackupProto_Contact.OneOf_Registration in
if !recipient.isRegistered {
var notRegistered = BackupProto_Contact.NotRegistered()
notRegistered.unregisteredTimestamp = recipient.unregisteredAtTimestamp ?? SignalRecipient.Constants.distantPastUnregisteredTimestamp
return .notRegistered(notRegistered)
}
return .registered(BackupProto.Contact.Registered())
}()
contact.aci = recipient.aci.map(\.rawUUID.data)
contact.pni = recipient.pni.map(\.rawUUID.data)
contact.e164 = { () -> UInt64? in
guard let phoneNumberString = recipient.phoneNumber?.stringValue else { return nil }
return E164(phoneNumberString)?.uint64Value
return .registered(BackupProto_Contact.Registered())
}()
if let aci = recipient.aci {
contact.username = usernameLookupManager.fetchUsername(
forAci: aci, transaction: tx
)
contact.aci = aci.rawUUID.data
if let username = usernameLookupManager.fetchUsername(forAci: aci, transaction: tx) {
contact.username = username
}
}
if let pni = recipient.pni {
contact.pni = pni.rawUUID.data
}
if
let phoneNumberString = recipient.phoneNumber?.stringValue,
let phoneNumberUInt = E164(phoneNumberString)?.uint64Value
{
contact.e164 = phoneNumberUInt
}
let userProfile = self.profileManager.getUserProfile(for: recipient.address, tx: tx)
contact.profileKey = userProfile?.profileKey.map(\.keyData)
contact.profileGivenName = userProfile?.givenName
contact.profileFamilyName = userProfile?.familyName
if let profileKey = userProfile?.profileKey {
contact.profileKey = profileKey.keyData
}
if let givenName = userProfile?.givenName {
contact.profileGivenName = givenName
}
if let familyName = userProfile?.familyName {
contact.profileFamilyName = familyName
}
Self.writeFrameToStream(
stream,
objectId: .contact(contactAddress),
frameBuilder: {
var recipient = BackupProto.Recipient(id: recipientId.value)
var recipient = BackupProto_Recipient()
recipient.id = recipientId.value
recipient.destination = .contact(contact)
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .recipient(recipient)
return frame
}
@@ -161,8 +170,8 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
}
func restoreContactRecipientProto(
_ contactProto: BackupProto.Contact,
recipient: BackupProto.Recipient,
_ contactProto: BackupProto_Contact,
recipient: BackupProto_Recipient,
context: MessageBackup.RecipientRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult {
@@ -193,33 +202,33 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
let pni: Pni?
let e164: E164?
let profileKey: OWSAES256Key?
if let aciRaw = contactProto.aci {
guard let aciUuid = UUID(data: aciRaw) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto.Contact.self)))
if contactProto.hasAci {
guard let aciUuid = UUID(data: contactProto.aci) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto_Contact.self)))
}
aci = Aci.init(fromUUID: aciUuid)
} else {
aci = nil
}
if let pniRaw = contactProto.pni {
guard let pniUuid = UUID(data: pniRaw) else {
return restoreFrameError(.invalidProtoData(.invalidPni(protoClass: BackupProto.Contact.self)))
if contactProto.hasPni {
guard let pniUuid = UUID(data: contactProto.pni) else {
return restoreFrameError(.invalidProtoData(.invalidPni(protoClass: BackupProto_Contact.self)))
}
pni = Pni.init(fromUUID: pniUuid)
} else {
pni = nil
}
if let contactProtoE164 = contactProto.e164 {
guard let protoE164 = E164(contactProtoE164) else {
return restoreFrameError(.invalidProtoData(.invalidE164(protoClass: BackupProto.Contact.self)))
if contactProto.hasE164 {
guard let protoE164 = E164(contactProto.e164) else {
return restoreFrameError(.invalidProtoData(.invalidE164(protoClass: BackupProto_Contact.self)))
}
e164 = protoE164
} else {
e164 = nil
}
if let contactProtoProfileKeyData = contactProto.profileKey {
guard let protoProfileKey = OWSAES256Key(data: contactProtoProfileKeyData) else {
return restoreFrameError(.invalidProtoData(.invalidProfileKey(protoClass: BackupProto.Contact.self)))
if contactProto.hasProfileKey {
guard let protoProfileKey = OWSAES256Key(data: contactProto.profileKey) else {
return restoreFrameError(.invalidProtoData(.invalidProfileKey(protoClass: BackupProto_Contact.self)))
}
profileKey = protoProfileKey
} else {
@@ -272,9 +281,9 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
if
let aci = recipient.aci,
let username = contactProto.username
contactProto.hasUsername
{
usernameLookupManager.saveUsername(username, forAci: aci, transaction: tx)
usernameLookupManager.saveUsername(contactProto.username, forAci: aci, transaction: tx)
}
if contactProto.profileSharing {
@@ -287,7 +296,7 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
}
switch contactProto.visibility {
case .HIDDEN, .HIDDEN_MESSAGE_REQUEST:
case .hidden, .hiddenMessageRequest:
/// Message-request state for hidden recipients isn't explicitly
/// tracked on iOS, and instead is derived from their hidden state
/// and the most-recent interactions in their 1:1 chat. So, for both
@@ -297,7 +306,7 @@ public class MessageBackupContactRecipientArchiver: MessageBackupProtoArchiver {
} catch let error {
return restoreFrameError(.databaseInsertionFailed(error))
}
case .VISIBLE:
case .visible, .UNRECOGNIZED:
break
}

View File

@@ -103,7 +103,7 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
}
// Ensure that explicit/blocklist have valid member recipient addresses
let privacyMode: BackupProto.DistributionList.PrivacyMode? = {
let privacyMode: BackupProto_DistributionList.PrivacyMode? = {
switch storyThread.storyViewMode {
case .disabled:
return nil
@@ -112,19 +112,19 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
errors.append(.archiveFrameError(.distributionListUnexpectedRecipients, distributionListAppId))
return nil
}
return .ALL
return .all
case .explicit:
guard memberRecipientIds.count > 0 else {
errors.append(.archiveFrameError(.distributionListMissingRecipients, distributionListAppId))
return nil
}
return .ONLY_WITH
return .onlyWith
case .blockList:
guard memberRecipientIds.count > 0 else {
errors.append(.archiveFrameError(.distributionListMissingRecipients, distributionListAppId))
return nil
}
return .ALL_EXCEPT
return .allExcept
}
}()
@@ -133,21 +133,22 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
return
}
var distributionList = BackupProto.DistributionList(
name: storyThread.name,
allowReplies: storyThread.allowsReplies,
privacyMode: privacyMode
)
var distributionList = BackupProto_DistributionList()
distributionList.name = storyThread.name
distributionList.allowReplies = storyThread.allowsReplies
distributionList.privacyMode = privacyMode
distributionList.memberRecipientIds = memberRecipientIds
var distributionListItem = BackupProto.DistributionListItem(distributionId: distributionId)
var distributionListItem = BackupProto_DistributionListItem()
distributionListItem.distributionID = distributionId
distributionListItem.item = .distributionList(distributionList)
Self.writeFrameToStream(stream, objectId: distributionListAppId) {
var recipient = BackupProto.Recipient(id: recipientId.value)
var recipient = BackupProto_Recipient()
recipient.id = recipientId.value
recipient.destination = .distributionList(distributionListItem)
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .recipient(recipient)
return frame
}.map { errors.append($0) }
@@ -172,22 +173,24 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
let recipientId = context.assignRecipientId(to: distributionListAppId)
var distributionList = BackupProto.DistributionListItem(distributionId: distributionId)
var distributionList = BackupProto_DistributionListItem()
distributionList.distributionID = distributionId
distributionList.item = .deletionTimestamp(deletionTimestamp)
Self.writeFrameToStream(stream, objectId: distributionListAppId) {
var recipient = BackupProto.Recipient(id: recipientId.value)
var recipient = BackupProto_Recipient()
recipient.id = recipientId.value
recipient.destination = .distributionList(distributionList)
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .recipient(recipient)
return frame
}.map { errors.append($0) }
}
func restoreDistributionListRecipientProto(
_ distributionListItemProto: BackupProto.DistributionListItem,
recipient: BackupProto.Recipient,
_ distributionListItemProto: BackupProto_DistributionListItem,
recipient: BackupProto_Recipient,
context: MessageBackup.RecipientRestoringContext,
tx: any DBWriteTransaction
) -> RestoreFrameResult {
@@ -198,7 +201,7 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
return .failure([.restoreFrameError(error, recipient.recipientId, line: line)])
}
guard let distributionId = UUID(data: distributionListItemProto.distributionId) else {
guard let distributionId = UUID(data: distributionListItemProto.distributionID) else {
return restoreFrameError(.invalidProtoData(.invalidDistributionListId))
}
@@ -234,12 +237,12 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
result = restoreFrameError(.invalidProtoData(.distributionListItemMissingItem))
}
context[recipient.recipientId] = .distributionList(distributionListItemProto.distributionId)
context[recipient.recipientId] = .distributionList(distributionListItemProto.distributionID)
return result
}
private func buildDistributionList(
from distributionListProto: BackupProto.DistributionList,
from distributionListProto: BackupProto_DistributionList,
distributionId: UUID,
recipientId: MessageBackup.RecipientId,
context: MessageBackup.RecipientRestoringContext,
@@ -255,7 +258,7 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
return contactAddress.asInteropAddress()
case .distributionList, .group, .localAddress, .releaseNotesChannel, .none:
error = .failure([.restoreFrameError(
.invalidProtoData(.invalidDistributionListMember(protoClass: BackupProto.DistributionList.self)),
.invalidProtoData(.invalidDistributionListMember(protoClass: BackupProto_DistributionList.self)),
recipientId
)])
return nil
@@ -268,13 +271,13 @@ public class MessageBackupDistributionListRecipientArchiver: MessageBackupProtoA
let viewMode: TSThreadStoryViewMode? = {
switch distributionListProto.privacyMode {
case .ALL:
case .all:
return .default
case .ALL_EXCEPT:
case .allExcept:
return .blockList
case .ONLY_WITH:
case .onlyWith:
return .explicit
case .UNKNOWN:
case .unknown, .UNRECOGNIZED:
return nil
}
}()

View File

@@ -6,10 +6,10 @@
import Foundation
import LibSignalClient
/// Archives ``TSGroupThread``s as ``BackupProto.Group`` recipients.
/// Archives ``TSGroupThread``s as ``BackupProto_Group`` recipients.
///
/// This is a bit confusing, because ``TSThread`` mostly corresponds to
/// ``BackupProto.Chat``, and there will in fact _also_ be a chat for the group
/// ``BackupProto_Chat``, and there will in fact _also_ be a chat for the group
/// thread. Its just that our group thread contains all the metadata
/// corresponding to both the Chat and Recipient parts of the Backup proto.
public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
@@ -104,38 +104,40 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
return
}
var group = BackupProto.Group(
masterKey: groupMasterKey,
whitelisted: profileManager.isThread(
inProfileWhitelist: groupThread, tx: tx
),
hideStory: storyStore.getOrCreateStoryContextAssociatedData(
forGroupThread: groupThread, tx: tx
).isHidden,
storySendMode: { () -> BackupProto.Group.StorySendMode in
switch groupThread.storyViewMode {
case .disabled: return .DISABLED
case .explicit, .blockList: return .ENABLED
case .default: return .DEFAULT
}
}()
var group = BackupProto_Group()
group.masterKey = groupMasterKey
group.whitelisted = profileManager.isThread(
inProfileWhitelist: groupThread, tx: tx
)
group.snapshot = { () -> BackupProto.Group.GroupSnapshot in
var groupSnapshot = BackupProto.Group.GroupSnapshot(
publicKey: groupPublicKey,
avatarUrl: groupModel.avatarUrlPath ?? "",
version: groupModel.revision,
inviteLinkPassword: groupModel.inviteLinkPassword ?? Data(),
announcementsOnly: groupModel.isAnnouncementsOnly
)
groupSnapshot.title = groupModel.groupName?.nilIfEmpty.map { .buildTitle($0) }
groupSnapshot.descriptionText = groupModel.descriptionText?.nilIfEmpty.map { .buildDescriptionText($0) }
groupSnapshot.disappearingMessagesTimer = { () -> BackupProto.Group.GroupAttributeBlob? in
group.hideStory = storyStore.getOrCreateStoryContextAssociatedData(
forGroupThread: groupThread, tx: tx
).isHidden
group.storySendMode = { () -> BackupProto_Group.StorySendMode in
switch groupThread.storyViewMode {
case .disabled: return .disabled
case .explicit, .blockList: return .enabled
case .default: return .default
}
}()
group.snapshot = { () -> BackupProto_Group.GroupSnapshot in
var groupSnapshot = BackupProto_Group.GroupSnapshot()
groupSnapshot.publicKey = groupPublicKey
groupSnapshot.avatarURL = groupModel.avatarUrlPath ?? ""
groupSnapshot.version = groupModel.revision
groupSnapshot.inviteLinkPassword = groupModel.inviteLinkPassword ?? Data()
groupSnapshot.announcementsOnly = groupModel.isAnnouncementsOnly
if let groupName = groupModel.groupName?.nilIfEmpty {
groupSnapshot.title = .buildTitle(groupName)
}
if let groupDescription = groupModel.descriptionText?.nilIfEmpty {
groupSnapshot.description_p = .buildDescriptionText(groupDescription)
}
groupSnapshot.disappearingMessagesTimer = { () -> BackupProto_Group.GroupAttributeBlob in
let durationSeconds = disappearingMessageConfigStore.durationSeconds(for: groupThread, tx: tx)
return durationSeconds > 0 ? .buildDisappearingMessageTimer(durationSeconds) : nil
return .buildDisappearingMessageTimer(durationSeconds)
}()
groupSnapshot.accessControl = groupModel.access.asBackupProtoAccessControl
groupSnapshot.members = groupMembership.fullMembers.compactMap { address -> BackupProto.Group.Member? in
groupSnapshot.members = groupMembership.fullMembers.compactMap { address -> BackupProto_Group.Member? in
guard
let aci = address.aci,
let role = groupMembership.role(for: address),
@@ -147,7 +149,7 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
return .build(serviceId: aci, role: role, profileKeyData: profileKey)
}
groupSnapshot.membersPendingProfileKey = groupMembership.invitedMembers.compactMap { address -> BackupProto.Group.MemberPendingProfileKey? in
groupSnapshot.membersPendingProfileKey = groupMembership.invitedMembers.compactMap { address -> BackupProto_Group.MemberPendingProfileKey? in
guard
let serviceId = address.serviceId,
let role = groupMembership.role(for: address),
@@ -159,10 +161,9 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
// iOS doesn't track the timestamp of the invite, so we'll
// default-populate it.
var invitedMemberProto = BackupProto.Group.MemberPendingProfileKey(
addedByUserId: addedByAci.serviceIdBinary.asData,
timestamp: 0
)
var invitedMemberProto = BackupProto_Group.MemberPendingProfileKey()
invitedMemberProto.addedByUserID = addedByAci.serviceIdBinary.asData
invitedMemberProto.timestamp = 0
invitedMemberProto.member = .build(
serviceId: serviceId,
role: role,
@@ -170,7 +171,7 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
)
return invitedMemberProto
}
groupSnapshot.membersPendingAdminApproval = groupMembership.requestingMembers.compactMap { address -> BackupProto.Group.MemberPendingAdminApproval? in
groupSnapshot.membersPendingAdminApproval = groupMembership.requestingMembers.compactMap { address -> BackupProto_Group.MemberPendingAdminApproval? in
guard
let aci = address.aci,
let profileKey = profileManager.getProfileKeyData(for: address, tx: tx)
@@ -181,17 +182,19 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
// iOS doesn't track the timestamp of the request, so we'll
// default-populate it.
return BackupProto.Group.MemberPendingAdminApproval(
userId: aci.serviceIdBinary.asData,
profileKey: profileKey,
timestamp: 0
)
var memberPendingAdminApproval = BackupProto_Group.MemberPendingAdminApproval()
memberPendingAdminApproval.userID = aci.serviceIdBinary.asData
memberPendingAdminApproval.profileKey = profileKey
memberPendingAdminApproval.timestamp = 0
return memberPendingAdminApproval
}
groupSnapshot.membersBanned = groupMembership.bannedMembers.map { aci, bannedAtMillis -> BackupProto.Group.MemberBanned in
return BackupProto.Group.MemberBanned(
userId: aci.serviceIdBinary.asData,
timestamp: bannedAtMillis
)
groupSnapshot.membersBanned = groupMembership.bannedMembers.map { aci, bannedAtMillis -> BackupProto_Group.MemberBanned in
var memberBanned = BackupProto_Group.MemberBanned()
memberBanned.userID = aci.serviceIdBinary.asData
memberBanned.timestamp = bannedAtMillis
return memberBanned
}
return groupSnapshot
@@ -201,10 +204,11 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
stream,
objectId: groupAppId,
frameBuilder: {
var recipient = BackupProto.Recipient(id: recipientId.value)
var recipient = BackupProto_Recipient()
recipient.id = recipientId.value
recipient.destination = .group(group)
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .recipient(recipient)
return frame
}
@@ -212,8 +216,8 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
}
func restoreGroupRecipientProto(
_ groupProto: BackupProto.Group,
recipient: BackupProto.Recipient,
_ groupProto: BackupProto_Group,
recipient: BackupProto_Recipient,
context: MessageBackup.RecipientRestoringContext,
tx: DBWriteTransaction
) -> RestoreFrameResult {
@@ -233,17 +237,18 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
return restoreFrameError(.invalidProtoData(.invalidGV2MasterKey))
}
guard let groupSnapshot = groupProto.snapshot else {
guard groupProto.hasSnapshot else {
return restoreFrameError(.invalidProtoData(.missingGV2GroupSnapshot))
}
let groupSnapshot = groupProto.snapshot
var groupMembershipBuilder = GroupMembership.Builder()
for fullMember in groupSnapshot.members {
guard let aci = try? Aci.parseFrom(serviceIdBinary: fullMember.userId) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto.Group.Member.self)))
guard let aci = try? Aci.parseFrom(serviceIdBinary: fullMember.userID) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto_Group.Member.self)))
}
guard let role = TSGroupMemberRole(backupProtoRole: fullMember.role) else {
return restoreFrameError(.invalidProtoData(.unrecognizedGV2MemberRole(protoClass: BackupProto.Group.Member.self)))
return restoreFrameError(.invalidProtoData(.unrecognizedGV2MemberRole(protoClass: BackupProto_Group.Member.self)))
}
groupMembershipBuilder.addFullMember(aci, role: role)
@@ -261,17 +266,18 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
}
}
for invitedMember in groupSnapshot.membersPendingProfileKey {
guard let memberDetails = invitedMember.member else {
guard invitedMember.hasMember else {
return restoreFrameError(.invalidProtoData(.invitedGV2MemberMissingMemberDetails))
}
guard let serviceId = try? ServiceId.parseFrom(serviceIdBinary: memberDetails.userId) else {
return restoreFrameError(.invalidProtoData(.invalidServiceId(protoClass: BackupProto.Group.MemberPendingProfileKey.self)))
let memberDetails = invitedMember.member
guard let serviceId = try? ServiceId.parseFrom(serviceIdBinary: memberDetails.userID) else {
return restoreFrameError(.invalidProtoData(.invalidServiceId(protoClass: BackupProto_Group.MemberPendingProfileKey.self)))
}
guard let role = TSGroupMemberRole(backupProtoRole: memberDetails.role) else {
return restoreFrameError(.invalidProtoData(.unrecognizedGV2MemberRole(protoClass: BackupProto.Group.MemberPendingProfileKey.self)))
return restoreFrameError(.invalidProtoData(.unrecognizedGV2MemberRole(protoClass: BackupProto_Group.MemberPendingProfileKey.self)))
}
guard let addedByAci = try? Aci.parseFrom(serviceIdBinary: invitedMember.addedByUserId) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto.Group.MemberPendingProfileKey.self)))
guard let addedByAci = try? Aci.parseFrom(serviceIdBinary: invitedMember.addedByUserID) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto_Group.MemberPendingProfileKey.self)))
}
groupMembershipBuilder.addInvitedMember(
@@ -281,8 +287,8 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
)
}
for requestingMember in groupSnapshot.membersPendingAdminApproval {
guard let aci = try? Aci.parseFrom(serviceIdBinary: requestingMember.userId) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto.Group.MemberPendingAdminApproval.self)))
guard let aci = try? Aci.parseFrom(serviceIdBinary: requestingMember.userID) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto_Group.MemberPendingAdminApproval.self)))
}
groupMembershipBuilder.addRequestingMember(aci)
@@ -299,8 +305,8 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
}
}
for bannedMember in groupSnapshot.membersBanned {
guard let aci = try? Aci.parseFrom(serviceIdBinary: bannedMember.userId) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto.Group.MemberBanned.self)))
guard let aci = try? Aci.parseFrom(serviceIdBinary: bannedMember.userID) else {
return restoreFrameError(.invalidProtoData(.invalidAci(protoClass: BackupProto_Group.MemberBanned.self)))
}
let bannedAtTimestampMillis = bannedMember.timestamp
@@ -318,9 +324,9 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
groupModelBuilder.name = groupSnapshot.extractTitle
groupModelBuilder.descriptionText = groupSnapshot.extractDescriptionText
groupModelBuilder.avatarData = nil
groupModelBuilder.avatarUrlPath = groupSnapshot.avatarUrl.nilIfEmpty
groupModelBuilder.avatarUrlPath = groupSnapshot.avatarURL.nilIfEmpty
groupModelBuilder.groupMembership = groupMembershipBuilder.build()
groupModelBuilder.groupAccess = groupSnapshot.accessControl.map(GroupAccess.init(backupProtoAccessControl:))
groupModelBuilder.groupAccess = GroupAccess(backupProtoAccessControl: groupSnapshot.accessControl)
groupModelBuilder.inviteLinkPassword = groupSnapshot.inviteLinkPassword.nilIfEmpty
groupModelBuilder.isAnnouncementsOnly = groupSnapshot.announcementsOnly
@@ -350,12 +356,12 @@ public class MessageBackupGroupRecipientArchiver: MessageBackupProtoArchiver {
let isStorySendEnabled: Bool? = {
switch groupProto.storySendMode {
case .DEFAULT:
case .default, .UNRECOGNIZED:
// No explicit setting.
return nil
case .DISABLED:
case .disabled:
return false
case .ENABLED:
case .enabled:
return true
}
}()
@@ -403,43 +409,43 @@ private extension OWSAES256Key {
// MARK: -
private extension BackupProto.Group.GroupAttributeBlob {
static func buildTitle(_ title: String) -> BackupProto.Group.GroupAttributeBlob {
var blob = BackupProto.Group.GroupAttributeBlob()
private extension BackupProto_Group.GroupAttributeBlob {
static func buildTitle(_ title: String) -> BackupProto_Group.GroupAttributeBlob {
var blob = BackupProto_Group.GroupAttributeBlob()
blob.content = .title(title)
return blob
}
static func buildDescriptionText(_ descriptionText: String) -> BackupProto.Group.GroupAttributeBlob {
var blob = BackupProto.Group.GroupAttributeBlob()
static func buildDescriptionText(_ descriptionText: String) -> BackupProto_Group.GroupAttributeBlob {
var blob = BackupProto_Group.GroupAttributeBlob()
blob.content = .descriptionText(descriptionText)
return blob
}
static func buildDisappearingMessageTimer(_ disappearingMessageDuration: UInt32) -> BackupProto.Group.GroupAttributeBlob {
var blob = BackupProto.Group.GroupAttributeBlob()
static func buildDisappearingMessageTimer(_ disappearingMessageDuration: UInt32) -> BackupProto_Group.GroupAttributeBlob {
var blob = BackupProto_Group.GroupAttributeBlob()
blob.content = .disappearingMessagesDuration(disappearingMessageDuration)
return blob
}
}
private extension BackupProto.Group.GroupSnapshot {
private extension BackupProto_Group.GroupSnapshot {
var extractTitle: String? {
switch title?.content {
switch title.content {
case .title(let title): return title
case nil, .avatar, .descriptionText, .disappearingMessagesDuration: return nil
}
}
var extractDescriptionText: String? {
switch descriptionText?.content {
switch description_p.content {
case .descriptionText(let descriptionText): return descriptionText
case nil, .title, .avatar, .disappearingMessagesDuration: return nil
}
}
var extractDisappearingMessageTimer: UInt32? {
switch disappearingMessagesTimer?.content {
switch disappearingMessagesTimer.content {
case .disappearingMessagesDuration(let disappearingMessageDuration): return disappearingMessageDuration
case nil, .title, .avatar, .descriptionText: return nil
}
@@ -448,37 +454,37 @@ private extension BackupProto.Group.GroupSnapshot {
// MARK: -
private extension BackupProto.Group.Member {
private extension BackupProto_Group.Member {
static func build(
serviceId: ServiceId,
role: TSGroupMemberRole,
profileKeyData: Data?
) -> BackupProto.Group.Member {
) -> BackupProto_Group.Member {
// iOS doesn't track the joinedAtRevision, so we'll default-populate it.
return BackupProto.Group.Member(
userId: serviceId.serviceIdBinary.asData,
role: role.asBackupProtoRole,
profileKey: profileKeyData ?? Data(),
joinedAtVersion: 0
)
var member = BackupProto_Group.Member()
member.userID = serviceId.serviceIdBinary.asData
member.role = role.asBackupProtoRole
member.profileKey = profileKeyData ?? Data()
member.joinedAtVersion = 0
return member
}
}
// MARK: -
private extension TSGroupMemberRole {
init?(backupProtoRole: BackupProto.Group.Member.Role) {
init?(backupProtoRole: BackupProto_Group.Member.Role) {
switch backupProtoRole {
case .UNKNOWN: return nil
case .DEFAULT: self = .normal
case .ADMINISTRATOR: self = .administrator
case .unknown, .UNRECOGNIZED: return nil
case .default: self = .normal
case .administrator: self = .administrator
}
}
var asBackupProtoRole: BackupProto.Group.Member.Role {
var asBackupProtoRole: BackupProto_Group.Member.Role {
switch self {
case .normal: return .DEFAULT
case .administrator: return .ADMINISTRATOR
case .normal: return .default
case .administrator: return .administrator
}
}
}
@@ -486,29 +492,29 @@ private extension TSGroupMemberRole {
// MARK: -
private extension GroupV2Access {
init(backupProtoAccessRequired: BackupProto.Group.AccessControl.AccessRequired) {
init(backupProtoAccessRequired: BackupProto_Group.AccessControl.AccessRequired) {
switch backupProtoAccessRequired {
case .UNKNOWN: self = .unknown
case .ANY: self = .any
case .MEMBER: self = .member
case .ADMINISTRATOR: self = .administrator
case .UNSATISFIABLE: self = .unsatisfiable
case .unknown, .UNRECOGNIZED: self = .unknown
case .any: self = .any
case .member: self = .member
case .administrator: self = .administrator
case .unsatisfiable: self = .unsatisfiable
}
}
var asBackupProtoAccessRequired: BackupProto.Group.AccessControl.AccessRequired {
var asBackupProtoAccessRequired: BackupProto_Group.AccessControl.AccessRequired {
switch self {
case .unknown: return .UNKNOWN
case .any: return .ANY
case .member: return .MEMBER
case .administrator: return .ADMINISTRATOR
case .unsatisfiable: return .UNSATISFIABLE
case .unknown: return .unknown
case .any: return .any
case .member: return .member
case .administrator: return .administrator
case .unsatisfiable: return .unsatisfiable
}
}
}
private extension GroupAccess {
convenience init(backupProtoAccessControl: BackupProto.Group.AccessControl) {
convenience init(backupProtoAccessControl: BackupProto_Group.AccessControl) {
self.init(
members: GroupV2Access(backupProtoAccessRequired: backupProtoAccessControl.members),
attributes: GroupV2Access(backupProtoAccessRequired: backupProtoAccessControl.attributes),
@@ -516,11 +522,11 @@ private extension GroupAccess {
)
}
var asBackupProtoAccessControl: BackupProto.Group.AccessControl {
return BackupProto.Group.AccessControl(
attributes: attributes.asBackupProtoAccessRequired,
members: members.asBackupProtoAccessRequired,
addFromInviteLink: addFromInviteLink.asBackupProtoAccessRequired
)
var asBackupProtoAccessControl: BackupProto_Group.AccessControl {
var accessControl = BackupProto_Group.AccessControl()
accessControl.attributes = attributes.asBackupProtoAccessRequired
accessControl.members = members.asBackupProtoAccessRequired
accessControl.addFromInviteLink = members.asBackupProtoAccessRequired
return accessControl
}
}

View File

@@ -13,7 +13,7 @@ extension MessageBackup {
public typealias RestoreLocalRecipientResult = RestoreFrameResult<RecipientId>
}
/// Archiver for the ``BackupProto.SelfRecipient`` recipient, a.k.a. the local
/// Archiver for the ``BackupProto_Self`` recipient, a.k.a. the local
/// user author/recipient. Used as the recipient for the Note To Self chat.
public class MessageBackupLocalRecipientArchiver: MessageBackupProtoArchiver {
private static let localRecipientId = MessageBackup.RecipientId(value: 1)
@@ -26,12 +26,13 @@ public class MessageBackupLocalRecipientArchiver: MessageBackupProtoArchiver {
stream,
objectId: MessageBackup.LocalRecipientId()
) {
let selfRecipient = BackupProto.SelfRecipient()
let selfRecipient = BackupProto_Self()
var recipient = BackupProto.Recipient(id: Self.localRecipientId.value)
recipient.destination = .selfRecipient(selfRecipient)
var recipient = BackupProto_Recipient()
recipient.id = Self.localRecipientId.value
recipient.destination = .self_p(selfRecipient)
var frame = BackupProto.Frame()
var frame = BackupProto_Frame()
frame.item = .recipient(recipient)
return frame
}
@@ -45,8 +46,8 @@ public class MessageBackupLocalRecipientArchiver: MessageBackupProtoArchiver {
/// Restore a single ``BackupProto/Recipient`` frame for the local recipient.
public func restoreSelfRecipient(
_ selfRecipientProto: BackupProto.SelfRecipient,
recipient: BackupProto.Recipient,
_ selfRecipientProto: BackupProto_Self,
recipient: BackupProto_Recipient,
context: MessageBackup.RecipientRestoringContext,
tx: DBWriteTransaction
) -> MessageBackup.RestoreLocalRecipientResult {

View File

@@ -34,8 +34,8 @@ public class MessageBackupReleaseNotesRecipientArchiver: MessageBackupProtoArchi
// MARK: -
func restoreReleaseNotesRecipientProto(
_ releaseNotesRecipientProto: BackupProto.ReleaseNotes,
recipient: BackupProto.Recipient,
_ releaseNotesRecipientProto: BackupProto_ReleaseNotes,
recipient: BackupProto_Recipient,
context: MessageBackup.RecipientRestoringContext,
tx: any DBWriteTransaction
) -> RestoreFrameResult {

View File

@@ -15,28 +15,28 @@ extension MessageBackup {
self.value = value
}
fileprivate init(recipient: BackupProto.Recipient) {
fileprivate init(recipient: BackupProto_Recipient) {
self.init(value: recipient.id)
}
fileprivate init(chat: BackupProto.Chat) {
self.init(value: chat.recipientId)
fileprivate init(chat: BackupProto_Chat) {
self.init(value: chat.recipientID)
}
fileprivate init(chatItem: BackupProto.ChatItem) {
self.init(value: chatItem.authorId)
fileprivate init(chatItem: BackupProto_ChatItem) {
self.init(value: chatItem.authorID)
}
fileprivate init(reaction: BackupProto.Reaction) {
self.init(value: reaction.authorId)
fileprivate init(reaction: BackupProto_Reaction) {
self.init(value: reaction.authorID)
}
fileprivate init(quote: BackupProto.Quote) {
self.init(value: quote.authorId)
fileprivate init(quote: BackupProto_Quote) {
self.init(value: quote.authorID)
}
fileprivate init(sendStatus: BackupProto.SendStatus) {
self.init(value: sendStatus.recipientId)
fileprivate init(sendStatus: BackupProto_SendStatus) {
self.init(value: sendStatus.recipientID)
}
}
@@ -48,7 +48,7 @@ extension MessageBackup {
* to the ID addressing system of the backup protos.
*
* For example, we will assign a ``BackupRecipientId`` to each ``SignalRecipient`` as we
* insert them. Later, when we create the ``BackupProto.Chat`` corresponding to the ``TSContactThread``
* insert them. Later, when we create the ``BackupProto_Chat`` corresponding to the ``TSContactThread``
* for that recipient, we will need to add the corresponding ``BackupRecipientId``, which we look up
* using the contact's Aci/Pni/e164, from the map this context keeps.
*/
@@ -165,7 +165,7 @@ extension MessageBackup {
}
extension MessageBackup.RecipientId: MessageBackupLoggableId {
public var typeLogString: String { "BackupProto.Recipient" }
public var typeLogString: String { "BackupProto_Recipient" }
public var idLogString: String { "\(self.value)" }
}
@@ -195,42 +195,42 @@ extension MessageBackup.RecipientArchivingContext.Address: MessageBackupLoggable
}
}
extension BackupProto.Recipient {
extension BackupProto_Recipient {
public var recipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(recipient: self)
}
}
extension BackupProto.Chat {
extension BackupProto_Chat {
public var typedRecipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(chat: self)
}
}
extension BackupProto.ChatItem {
extension BackupProto_ChatItem {
public var authorRecipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(chatItem: self)
}
}
extension BackupProto.Reaction {
extension BackupProto_Reaction {
public var authorRecipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(reaction: self)
}
}
extension BackupProto.Quote {
extension BackupProto_Quote {
public var authorRecipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(quote: self)
}
}
extension BackupProto.SendStatus {
extension BackupProto_SendStatus {
public var destinationRecipientId: MessageBackup.RecipientId {
return MessageBackup.RecipientId(sendStatus: self)
}

View File

@@ -4,7 +4,7 @@
//
public extension MessageBackup {
/// An identifier for a ``BackupProto.StickerPack`` backup frame.
/// An identifier for a ``BackupProto_StickerPack`` backup frame.
struct StickerPackId: MessageBackupLoggableId {
let value: Data
@@ -14,7 +14,7 @@ public extension MessageBackup {
// MARK: MessageBackupLoggableId
public var typeLogString: String { "BackupProto.StickPack" }
public var typeLogString: String { "BackupProto_StickPack" }
public var idLogString: String {
/// Since sticker pack IDs are a cross-client identifier, we don't
/// want to log them directly.

View File

@@ -3,8 +3,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
import Wire
extension MessageBackup {
public enum ProtoInputStreamReadResult<T> {
case success(T, moreBytesAvailable: Bool)
@@ -25,10 +23,10 @@ public protocol MessageBackupProtoInputStream {
/// Read the single header object at the start of every backup file.
/// If this header is missing or invalid, the backup should be discarded.
func readHeader() -> MessageBackup.ProtoInputStreamReadResult<BackupProto.BackupInfo>
func readHeader() -> MessageBackup.ProtoInputStreamReadResult<BackupProto_BackupInfo>
/// Read a the next frame from the backup file.
func readFrame() -> MessageBackup.ProtoInputStreamReadResult<BackupProto.Frame>
func readFrame() -> MessageBackup.ProtoInputStreamReadResult<BackupProto_Frame>
/// Close the stream. Attempting to read after closing will result in failures.
func closeFileStream()
@@ -47,17 +45,15 @@ internal class MessageBackupProtoInputStreamImpl: MessageBackupProtoInputStream
self.inputStreamDelegate = inputStreamDelegate
}
internal func readHeader() -> MessageBackup.ProtoInputStreamReadResult<BackupProto.BackupInfo> {
internal func readHeader() -> MessageBackup.ProtoInputStreamReadResult<BackupProto_BackupInfo> {
return readProto { protoData in
return try ProtoDecoder(enumDecodingStrategy: .returnNil)
.decode(BackupProto.BackupInfo.self, from: protoData)
return try BackupProto_BackupInfo(contiguousBytes: protoData)
}
}
internal func readFrame() -> MessageBackup.ProtoInputStreamReadResult<BackupProto.Frame> {
internal func readFrame() -> MessageBackup.ProtoInputStreamReadResult<BackupProto_Frame> {
return readProto { protoData in
return try ProtoDecoder(enumDecodingStrategy: .returnNil)
.decode(BackupProto.Frame.self, from: protoData)
return try BackupProto_Frame(contiguousBytes: protoData)
}
}

View File

@@ -3,8 +3,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
import Wire
extension MessageBackup {
public enum ProtoOutputStreamWriteResult {
case success
@@ -29,10 +27,10 @@ public protocol MessageBackupProtoOutputStream {
/// Write a header (BakckupInfo) to the backup file.
/// It is the caller's responsibility to ensure this is always written, and is the first thing written,
/// in order to produce a valid backup file.
func writeHeader(_ header: BackupProto.BackupInfo) -> MessageBackup.ProtoOutputStreamWriteResult
func writeHeader(_ header: BackupProto_BackupInfo) -> MessageBackup.ProtoOutputStreamWriteResult
/// Write a frame to the backup file.
func writeFrame(_ frame: BackupProto.Frame) -> MessageBackup.ProtoOutputStreamWriteResult
func writeFrame(_ frame: BackupProto_Frame) -> MessageBackup.ProtoOutputStreamWriteResult
/// Closes the output stream.
func closeFileStream() throws
@@ -46,10 +44,10 @@ internal class MessageBackupProtoOutputStreamImpl: MessageBackupProtoOutputStrea
self.outputStream = outputStream
}
internal func writeHeader(_ header: BackupProto.BackupInfo) -> MessageBackup.ProtoOutputStreamWriteResult {
internal func writeHeader(_ header: BackupProto_BackupInfo) -> MessageBackup.ProtoOutputStreamWriteResult {
let bytes: Data
do {
bytes = try ProtoEncoder().encode(header)
bytes = try header.serializedData()
} catch {
return .protoSerializationError(error)
}
@@ -61,10 +59,10 @@ internal class MessageBackupProtoOutputStreamImpl: MessageBackupProtoOutputStrea
return .success
}
internal func writeFrame(_ frame: BackupProto.Frame) -> MessageBackup.ProtoOutputStreamWriteResult {
internal func writeFrame(_ frame: BackupProto_Frame) -> MessageBackup.ProtoOutputStreamWriteResult {
let bytes: Data
do {
bytes = try ProtoEncoder().encode(frame)
bytes = try frame.serializedData()
} catch {
return .protoSerializationError(error)
}

View File

@@ -4,7 +4,7 @@
//
extension MessageBackup {
/// An identifier for an empty ``BackupProto.Frame``.
/// An identifier for an empty ``BackupProto_Frame``.
///
/// Uses a singleton pattern, as frames do not contain their own ID and
/// consequently all empty frames are equivalent.

View File

@@ -316,10 +316,10 @@ public class MessageBackupManagerImpl: MessageBackupManager {
}
private func writeHeader(stream: MessageBackupProtoOutputStream, tx: DBWriteTransaction) throws {
let backupInfo = BackupProto.BackupInfo(
version: Constants.supportedBackupVersion,
backupTimeMs: dateProvider().ows_millisecondsSince1970
)
var backupInfo = BackupProto_BackupInfo()
backupInfo.version = Constants.supportedBackupVersion
backupInfo.backupTimeMs = dateProvider().ows_millisecondsSince1970
switch stream.writeHeader(backupInfo) {
case .success:
break
@@ -416,7 +416,7 @@ public class MessageBackupManagerImpl: MessageBackupManager {
tx: DBWriteTransaction
) throws {
let backupInfo: BackupProto.BackupInfo
let backupInfo: BackupProto_BackupInfo
var hasMoreFrames = false
switch stream.readHeader() {
case .success(let header, let moreBytesAvailable):
@@ -441,7 +441,7 @@ public class MessageBackupManagerImpl: MessageBackupManager {
)
while hasMoreFrames {
let frame: BackupProto.Frame
let frame: BackupProto_Frame
switch stream.readFrame() {
case let .success(_frame, moreBytesAvailable):
frame = _frame
@@ -463,7 +463,7 @@ public class MessageBackupManagerImpl: MessageBackupManager {
.invalidProtoData(.recipientMissingDestination),
recipient.recipientId
)])
case .selfRecipient(let selfRecipientProto):
case .self_p(let selfRecipientProto):
recipientResult = localRecipientArchiver.restoreSelfRecipient(
selfRecipientProto,
recipient: recipient,
@@ -553,15 +553,15 @@ public class MessageBackupManagerImpl: MessageBackupManager {
// TODO: [Backups] Restore sticker packs.
try processRestoreFrameErrors(errors: [.restoreFrameError(
.unimplemented,
MessageBackup.StickerPackId(backupProtoStickerPack.packId)
MessageBackup.StickerPackId(backupProtoStickerPack.packID)
)])
case .adHocCall(let backupProtoAdHocCall):
// TODO: [Backups] Restore ad-hoc calls.
try processRestoreFrameErrors(errors: [.restoreFrameError(
.unimplemented,
MessageBackup.AdHocCallId(
backupProtoAdHocCall.callId,
recipientId: backupProtoAdHocCall.recipientId
backupProtoAdHocCall.callID,
recipientId: backupProtoAdHocCall.recipientID
)
)])
case nil:

View File

@@ -115,37 +115,41 @@ public struct ArchivedPayment: Codable, Hashable, FetchableRecord, PersistableRe
}
extension ArchivedPayment {
func toTransactionDetailsProto() -> BackupProto.PaymentNotification.TransactionDetails {
var transactionDetails = BackupProto.PaymentNotification.TransactionDetails()
func toTransactionDetailsProto() -> BackupProto_PaymentNotification.TransactionDetails {
var transactionDetails = BackupProto_PaymentNotification.TransactionDetails()
if status.isFailure {
let reason: BackupProto.PaymentNotification.TransactionDetails.FailedTransaction.FailureReason = {
let reason: BackupProto_PaymentNotification.TransactionDetails.FailedTransaction.FailureReason = {
switch failureReason {
case .genericFailure: return .GENERIC
case .networkFailure: return .NETWORK
case .insufficientFundsFailure: return .INSUFFICIENT_FUNDS
case .genericFailure: return .generic
case .networkFailure: return .network
case .insufficientFundsFailure: return .insufficientFunds
case .none:
owsFailDebug("Invalid status for failure type")
return .GENERIC
return .generic
}
}()
transactionDetails.payment = .failedTransaction(.init(reason: reason))
var failedTransaction = BackupProto_PaymentNotification.TransactionDetails.FailedTransaction()
failedTransaction.reason = reason
transactionDetails.payment = .failedTransaction(failedTransaction)
} else {
let success: BackupProto.PaymentNotification.TransactionDetails.Transaction.Status = {
let success: BackupProto_PaymentNotification.TransactionDetails.Transaction.Status = {
switch status {
case .initial: return .INITIAL
case .submitted: return .SUBMITTED
case .successful: return .SUCCESSFUL
case .initial: return .initial
case .submitted: return .submitted
case .successful: return .successful
case .error:
owsFailDebug("Invalid status for success type")
return .SUCCESSFUL
return .successful
}
}()
var transaction = BackupProto.PaymentNotification.TransactionDetails.Transaction(status: success)
var transaction = BackupProto_PaymentNotification.TransactionDetails.Transaction()
transaction.status = success
var identification = BackupProto.PaymentNotification.TransactionDetails.MobileCoinTxoIdentification()
var identification = BackupProto_PaymentNotification.TransactionDetails.MobileCoinTxoIdentification()
if let keyImages = mobileCoinIdentification?.keyImages {
identification.keyImages = keyImages
}
@@ -154,11 +158,11 @@ extension ArchivedPayment {
}
transaction.mobileCoinIdentification = identification
transaction.timestamp = timestamp
transaction.blockIndex = blockIndex
transaction.blockTimestamp = blockTimestamp
transaction.transaction = self.transaction
transaction.receipt = receipt
if let timestamp { transaction.timestamp = timestamp }
if let blockIndex { transaction.blockIndex = blockIndex }
if let blockTimestamp { transaction.blockIndex = blockTimestamp }
if let _transaction = self.transaction { transaction.transaction = _transaction }
if let receipt { transaction.receipt = receipt }
transactionDetails.payment = .transaction(transaction)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,7 @@
# Backup Proto
# Backup protos
The Backup protos are generated using [Wire](https://github.com/square/wire),
in contrast with the rest of the Signal-iOS protos which use (at the time of
writing) a combination of
[Swift-Protobuf](https://github.com/apple/swift-protobuf/) and bespoke
code-generation in [ProtoWrappers.py](../../../Scripts/protos/ProtoWrappers.py).
## `Swift-Protobuf`
Using `Wire` for Backups obviates the need for updates to `ProtoWrappers.py`,
and the models generated by `Wire` are easier to work with than those generated
by `ProtoWrappers.py`.
We use [`Swift-Protobuf`](https://github.com/apple/swift-protobuf) to generate Swift code for working with `Backup.proto`, much like we do for all our other proto definitions.
Additionally, the `Wire`-generated models expose `optional` protobuf fields as
`Optional` values in Swift. This is in contrast to `Swift-Protobuf`, which
exposes those fields as non-`Optional` (with a default value returned if none is
present) with `hasField` properties allowing the caller to inspect if a value
was explicitly set. While the `Swift-Protobuf` approach is arguably closer to
the raw behavior of protobufs, the `Wire` approach more directly supports the
type-safe calling patterns we want to use in code.
## How to generate models
See [compile-backups-proto-with-wire](../../../Scripts/protos/compile-backups-proto-with-wire).
That script reads the `Backup.proto` file in this directory, downloads the
`Wire` (if necessary), and runs it to generate models to the right place.
## Special considerations when using `Wire`
`Wire` does not support adding a prefix to type names for namespacing purposes.
To achieve the same result we instead nest all proto types in `Backup.proto`
under a top-level `message BackupProto`, such that when they are generated the
corresponding Swift types are nested under a generated (empty)
`struct BackupProto`.
However, unlike the other protos, we do not use the "wrapper" code generated by `$REPO_ROOT/Scripts/protos/ProtoWrappers.py` to wrap the `Swift-Protobuf`-generated code for Backups, because `ProtoWrappers.py` is incompatible with some of the syntactic structures we use in `Backup.proto`.

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
REPO_ROOT=$(git rev-parse --show-toplevel)
BACKUP_PROTO_DIR="$REPO_ROOT/SignalServiceKit/protobuf/Backups"
BACKUP_PROTO_FILE="$BACKUP_PROTO_DIR/Backup.proto"
BACKUP_SWIFT_FILE="$BACKUP_PROTO_DIR/Backup.pb.swift"
echo "Generating Backup.pb.swift file with protoc and Swift-Protobuf..."
protoc \
--proto_path="$BACKUP_PROTO_DIR" \
--swift_out="$BACKUP_PROTO_DIR" \
--swift_opt=Visibility=public \
"$BACKUP_PROTO_FILE"
"$REPO_ROOT"/Scripts/lint/lint-license-headers --fix "$BACKUP_PROTO_FILE"

View File

@@ -188,8 +188,8 @@ extension IncomingContactSyncJobRecord: ValidatableModel {
IncomingContactSyncJobRecord(
cdnNumber: 3,
cdnKey: "hello",
encryptionKey: Data(base64URLEncoded: "mMiOmZhbHNlLCJzdXBlciI6eyJ1b")!,
digest: Data(base64URLEncoded: "291bnQiOjYsInJlY29yZFR5cGUiO")!,
encryptionKey: Data(base64Encoded: "mMiOmZhbHNlLCJzdXBlciI6eyJ1b")!,
digest: Data(base64Encoded: "291bnQiOjYsInJlY29yZFR5cGUiO")!,
plaintextLength: 55,
isCompleteContactSync: true
),