From d958fda766891276322296376964d9a63dfdc1dd Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Fri, 4 Apr 2025 08:07:52 -0500 Subject: [PATCH] first pass on signal-server proto file --- example/signal.proto | 1970 ++++++++++++++++++++---------------------- 1 file changed, 952 insertions(+), 1018 deletions(-) diff --git a/example/signal.proto b/example/signal.proto index b7d3bc7..7d3da53 100644 --- a/example/signal.proto +++ b/example/signal.proto @@ -7,11 +7,11 @@ package signalbackups; option java_package = "org.thoughtcrime.securesms.backup.v2.proto"; message BackupInfo { - uint64 version = 1; - uint64 backupTimeMs = 2; - bytes mediaRootBackupKey = 3; // 32-byte random value generated when the backup is uploaded for the first time. - string currentAppVersion = 4; - string firstAppVersion = 5; + uint64 version = 1; + uint64 backupTimeMs = 2; + bytes mediaRootBackupKey = 3; // 32-byte random value generated when the backup is uploaded for the first time. + string currentAppVersion = 4; + string firstAppVersion = 5; } // Frames must follow in the following ordering rules: @@ -31,294 +31,269 @@ message BackupInfo { // For example, Chats may all be together at the beginning, // or may each immediately precede its first ChatItem. message Frame { - // If unset, importers should skip this frame without throwing an error. - oneof item { - AccountData account = 1; - Recipient recipient = 2; - Chat chat = 3; - ChatItem chatItem = 4; - StickerPack stickerPack = 5; - AdHocCall adHocCall = 6; - NotificationProfile notificationProfile = 7; - ChatFolder chatFolder = 8; - } -} + oneof item { + AccountData account = 1; + Recipient recipient = 2; + Chat chat = 3; + ChatItem chatItem = 4; + StickerPack stickerPack = 5; + AdHocCall adHocCall = 6; + NotificationProfile notificationProfile = 7; + ChatFolder chatFolder = 8; + } + // If unset, importers should skip this frame without throwing an error. +} message AccountData { - enum PhoneNumberSharingMode { - UNKNOWN = 0; // Interpret as "Nobody" - EVERYBODY = 1; - NOBODY = 2; - } - message UsernameLink { - enum Color { - UNKNOWN = 0; // Interpret as "Blue" - BLUE = 1; - WHITE = 2; - GREY = 3; - OLIVE = 4; - GREEN = 5; - ORANGE = 6; - PINK = 7; - PURPLE = 8; - } + enum PhoneNumberSharingMode { + UNKNOWN = 0; // Interpret as "Nobody" + EVERYBODY = 1; + NOBODY = 2; + } + message UsernameLink { + enum Color { + UNKNOWN = 0; // Interpret as "Blue" + BLUE = 1; + WHITE = 2; + GREY = 3; + OLIVE = 4; + GREEN = 5; + ORANGE = 6; + PINK = 7; + PURPLE = 8; + } + bytes entropy = 1; // 32 bytes of entropy used for encryption + bytes serverId = 2; // 16 bytes of encoded UUID provided by the server + Color color = 3; + } + message AccountSettings { + bool readReceipts = 1; + bool sealedSenderIndicators = 2; + bool typingIndicators = 3; + bool linkPreviews = 4; + bool notDiscoverableByPhoneNumber = 5; + bool preferContactAvatars = 6; + uint32 universalExpireTimerSeconds = 7; // 0 means no universal expire timer. + repeated string preferredReactionEmoji = 8; + bool displayBadgesOnProfile = 9; + bool keepMutedChatsArchived = 10; + bool hasSetMyStoriesPrivacy = 11; + bool hasViewedOnboardingStory = 12; + bool storiesDisabled = 13; + optional bool storyViewReceiptsEnabled = 14; + bool hasSeenGroupStoryEducationSheet = 15; + bool hasCompletedUsernameOnboarding = 16; + PhoneNumberSharingMode phoneNumberSharingMode = 17; + ChatStyle defaultChatStyle = 18; + repeated ChatStyle.CustomChatColor customChatColors = 19; + } + message SubscriberData { + bytes subscriberId = 1; + string currencyCode = 2; + bool manuallyCancelled = 3; + } + message IAPSubscriberData { + oneof iapSubscriptionId { + // Identifies an Android Play Store IAP subscription. + string purchaseToken = 2; + // Identifies an iOS App Store IAP subscription. + uint64 originalTransactionId = 3; + } - bytes entropy = 1; // 32 bytes of entropy used for encryption - bytes serverId = 2; // 16 bytes of encoded UUID provided by the server - Color color = 3; - } + bytes subscriberId = 1; - message AccountSettings { - bool readReceipts = 1; - bool sealedSenderIndicators = 2; - bool typingIndicators = 3; - bool linkPreviews = 4; - bool notDiscoverableByPhoneNumber = 5; - bool preferContactAvatars = 6; - uint32 universalExpireTimerSeconds = 7; // 0 means no universal expire timer. - repeated string preferredReactionEmoji = 8; - bool displayBadgesOnProfile = 9; - bool keepMutedChatsArchived = 10; - bool hasSetMyStoriesPrivacy = 11; - bool hasViewedOnboardingStory = 12; - bool storiesDisabled = 13; - optional bool storyViewReceiptsEnabled = 14; - bool hasSeenGroupStoryEducationSheet = 15; - bool hasCompletedUsernameOnboarding = 16; - PhoneNumberSharingMode phoneNumberSharingMode = 17; - ChatStyle defaultChatStyle = 18; - repeated ChatStyle.CustomChatColor customChatColors = 19; - } - - message SubscriberData { - bytes subscriberId = 1; - string currencyCode = 2; - bool manuallyCancelled = 3; - } - - message IAPSubscriberData { - bytes subscriberId = 1; - - // If unset, importers should ignore the subscriber data without throwing an error. - oneof iapSubscriptionId { - // Identifies an Android Play Store IAP subscription. - string purchaseToken = 2; - // Identifies an iOS App Store IAP subscription. - uint64 originalTransactionId = 3; - } - } - - bytes profileKey = 1; - optional string username = 2; - UsernameLink usernameLink = 3; - string givenName = 4; - string familyName = 5; - string avatarUrlPath = 6; - SubscriberData donationSubscriberData = 7; - reserved 8; // A deprecated format // backupsSubscriberData - AccountSettings accountSettings = 9; - IAPSubscriberData backupsSubscriberData = 10; - string svrPin = 11; + // If unset, importers should ignore the subscriber data without throwing an error. + } + bytes profileKey = 1; + optional string username = 2; + UsernameLink usernameLink = 3; + string givenName = 4; + string familyName = 5; + string avatarUrlPath = 6; + SubscriberData donationSubscriberData = 7; + = 8; // A deprecated format // backupsSubscriberData + AccountSettings accountSettings = 9; + IAPSubscriberData backupsSubscriberData = 10; + string svrPin = 11; } - message Recipient { - uint64 id = 1; // generated id for reference only within this file - // If unset, importers should skip this frame without throwing an error. - oneof destination { - Contact contact = 2; - Group group = 3; - DistributionListItem distributionList = 4; - Self self = 5; - ReleaseNotes releaseNotes = 6; - CallLink callLink = 7; - } -} + oneof destination { + Contact contact = 2; + Group group = 3; + DistributionListItem distributionList = 4; + Self self = 5; + ReleaseNotes releaseNotes = 6; + CallLink callLink = 7; + } -// If unset - computed as the value of the first byte of SHA-256(msg=CONTACT_ID) -// modulo the count of colors. Once set the avatar color for a recipient is -// never recomputed or changed. -// -// `CONTACT_ID` is the first available identifier from the list: -// - ServiceIdToBinary(ACI) -// - E164 -// - ServiceIdToBinary(PNI) -// - Group Id + uint64 id = 1; // generated id for reference only within this file + // If unset, importers should skip this frame without throwing an error. +} enum AvatarColor { - A100 = 0; - A110 = 1; - A120 = 2; - A130 = 3; - A140 = 4; - A150 = 5; - A160 = 6; - A170 = 7; - A180 = 8; - A190 = 9; - A200 = 10; - A210 = 11; + A100 = 0; + A110 = 1; + A120 = 2; + A130 = 3; + A140 = 4; + A150 = 5; + A160 = 6; + A170 = 7; + A180 = 8; + A190 = 9; + A200 = 10; + A210 = 11; } message Contact { - enum IdentityState { - DEFAULT = 0; // A valid value -- indicates unset by the user - VERIFIED = 1; - UNVERIFIED = 2; // Was once verified and is now unverified - } - - message Registered {} - message NotRegistered { - uint64 unregisteredTimestamp = 1; - } - - enum Visibility { - VISIBLE = 0; // A valid value -- the contact is not hidden - HIDDEN = 1; - HIDDEN_MESSAGE_REQUEST = 2; - } - - message Name { - string given = 1; - string family = 2; - } - - optional bytes aci = 1; // should be 16 bytes - optional bytes pni = 2; // should be 16 bytes - optional string username = 3; - optional uint64 e164 = 4; - bool blocked = 5; - Visibility visibility = 6; - - // If unset, consider the user to be registered - oneof registration { - Registered registered = 7; - NotRegistered notRegistered = 8; - } - - optional bytes profileKey = 9; - bool profileSharing = 10; - optional string profileGivenName = 11; - optional string profileFamilyName = 12; - bool hideStory = 13; - optional bytes identityKey = 14; - IdentityState identityState = 15; - Name nickname = 16; // absent iff both `given` and `family` are empty - string note = 17; - string systemGivenName = 18; - string systemFamilyName = 19; - string systemNickname = 20; - optional AvatarColor avatarColor = 21; + enum IdentityState { + DEFAULT = 0; // A valid value -- indicates unset by the user + VERIFIED = 1; + UNVERIFIED = 2; // Was once verified and is now unverified + } + // isEmpty +// footer was empty +message NotRegistered { +uint64 unregisteredTimestamp = 1; } +enum Visibility { +VISIBLE = 0; // A valid value -- the contact is not hidden +HIDDEN = 1; +HIDDEN_MESSAGE_REQUEST = 2; +} + +message Name { +string given = 1; +string family = 2; +} + +optional bytes aci = 1; // should be 16 bytes +optional bytes pni = 2; // should be 16 bytes +optional string username = 3; +optional uint64 e164 = 4; +bool blocked = 5; +Visibility visibility = 6; + +// If unset, consider the user to be registered +oneof registration { +Registered registered = 7; +NotRegistered notRegistered = 8; +} + +optional bytes profileKey = 9; +bool profileSharing = 10; +optional string profileGivenName = 11; +optional string profileFamilyName = 12; +bool hideStory = 13; +optional bytes identityKey = 14; +IdentityState identityState = 15; +Name nickname = 16; // absent iff both `given` and `family` are empty +string note = 17; +string systemGivenName = 18; +string systemFamilyName = 19; +string systemNickname = 20; +optional AvatarColor avatarColor = 21; +} message Group { - enum StorySendMode { - DEFAULT = 0; // A valid value -- indicates unset by the user - DISABLED = 1; - ENABLED = 2; - } + enum StorySendMode { + DEFAULT = 0; // A valid value -- indicates unset by the user + DISABLED = 1; + ENABLED = 2; + } + message GroupSnapshot { + = 1; // The field is deprecated in the context of static group state // publicKey + GroupAttributeBlob title = 2; + GroupAttributeBlob description = 11; + string avatarUrl = 3; + GroupAttributeBlob disappearingMessagesTimer = 4; + AccessControl accessControl = 5; + uint32 version = 6; + repeated Member members = 7; + repeated MemberPendingProfileKey membersPendingProfileKey = 8; + repeated MemberPendingAdminApproval membersPendingAdminApproval = 9; + bytes inviteLinkPassword = 10; + bool announcements_only = 12; + repeated MemberBanned members_banned = 13; + } + message GroupAttributeBlob { + oneof content { + string title = 1; + bytes avatar = 2; + uint32 disappearingMessagesDuration = 3; + string descriptionText = 4; + } + // If unset, consider the field it represents to not be present + } + message Member { + enum Role { + UNKNOWN = 0; // Intepret as "Default" + DEFAULT = 1; + ADMINISTRATOR = 2; + } + bytes userId = 1; + Role role = 2; + = 3; // This field is ignored in Backups, in favor of Contact frames for members // profileKey + = 4; // This field is deprecated in the context of static group state // presentation + uint32 joinedAtVersion = 5; + } + message MemberPendingProfileKey { + Member member = 1; + bytes addedByUserId = 2; + uint64 timestamp = 3; + } + message MemberPendingAdminApproval { + bytes userId = 1; + = 2; // This field is ignored in Backups, in favor of Contact frames for members // profileKey + = 3; // This field is deprecated in the context of static group state // presentation + uint64 timestamp = 4; + } + message MemberBanned { + bytes userId = 1; + uint64 timestamp = 2; + } + message AccessControl { + enum AccessRequired { + UNKNOWN = 0; // Intepret as "Unsatisfiable" + ANY = 1; + MEMBER = 2; + ADMINISTRATOR = 3; + UNSATISFIABLE = 4; + } - bytes masterKey = 1; - bool whitelisted = 2; - bool hideStory = 3; - StorySendMode storySendMode = 4; - GroupSnapshot snapshot = 5; - bool blocked = 6; - optional AvatarColor avatarColor = 7; + AccessRequired attributes = 1; + AccessRequired members = 2; + AccessRequired addFromInviteLink = 3; + } + bytes masterKey = 1; + bool whitelisted = 2; + bool hideStory = 3; + StorySendMode storySendMode = 4; + GroupSnapshot snapshot = 5; + bool blocked = 6; + optional AvatarColor avatarColor = 7; - // These are simply plaintext copies of the groups proto from Groups.proto. - // They should be kept completely in-sync with Groups.proto. - // These exist to allow us to have the latest snapshot of a group during restoration without having to hit the network. - // We would use Groups.proto if we could, but we want a plaintext version to improve export readability. - // For documentation, defer to Groups.proto. The only name change is Group -> GroupSnapshot to avoid the naming conflict. - message GroupSnapshot { - reserved 1; // The field is deprecated in the context of static group state // publicKey - GroupAttributeBlob title = 2; - GroupAttributeBlob description = 11; - string avatarUrl = 3; - GroupAttributeBlob disappearingMessagesTimer = 4; - AccessControl accessControl = 5; - uint32 version = 6; - repeated Member members = 7; - repeated MemberPendingProfileKey membersPendingProfileKey = 8; - repeated MemberPendingAdminApproval membersPendingAdminApproval = 9; - bytes inviteLinkPassword = 10; - bool announcements_only = 12; - repeated MemberBanned members_banned = 13; - } - - message GroupAttributeBlob { - // If unset, consider the field it represents to not be present - oneof content { - string title = 1; - bytes avatar = 2; - uint32 disappearingMessagesDuration = 3; - string descriptionText = 4; - } - } - - message Member { - enum Role { - UNKNOWN = 0; // Intepret as "Default" - DEFAULT = 1; - ADMINISTRATOR = 2; - } - - bytes userId = 1; - Role role = 2; - reserved 3; // This field is ignored in Backups, in favor of Contact frames for members // profileKey - reserved 4; // This field is deprecated in the context of static group state // presentation - uint32 joinedAtVersion = 5; - } - - message MemberPendingProfileKey { - Member member = 1; - bytes addedByUserId = 2; - uint64 timestamp = 3; - } - - message MemberPendingAdminApproval { - bytes userId = 1; - reserved 2; // This field is ignored in Backups, in favor of Contact frames for members // profileKey - reserved 3; // This field is deprecated in the context of static group state // presentation - uint64 timestamp = 4; - } - - message MemberBanned { - bytes userId = 1; - uint64 timestamp = 2; - } - - message AccessControl { - enum AccessRequired { - UNKNOWN = 0; // Intepret as "Unsatisfiable" - ANY = 1; - MEMBER = 2; - ADMINISTRATOR = 3; - UNSATISFIABLE = 4; - } - - AccessRequired attributes = 1; - AccessRequired members = 2; - AccessRequired addFromInviteLink = 3; - } + // These are simply plaintext copies of the groups proto from Groups.proto. + // They should be kept completely in-sync with Groups.proto. + // These exist to allow us to have the latest snapshot of a group during restoration without having to hit the network. + // We would use Groups.proto if we could, but we want a plaintext version to improve export readability. + // For documentation, defer to Groups.proto. The only name change is Group -> GroupSnapshot to avoid the naming conflict. } - message Self { - optional AvatarColor avatarColor = 1; + optional AvatarColor avatarColor = 1; } -message ReleaseNotes {} - +// isEmpty message Chat { - uint64 id = 1; // generated id for reference only within this file - uint64 recipientId = 2; - bool archived = 3; - optional uint32 pinnedOrder = 4; // will be displayed in ascending order - optional uint64 expirationTimerMs = 5; - optional uint64 muteUntilMs = 6; // INT64_MAX (2^63 - 1) = "always muted". - bool markedUnread = 7; - bool dontNotifyForMentionsIfMuted = 8; - ChatStyle style = 9; - uint32 expireTimerVersion = 10; + uint64 id = 1; // generated id for reference only within this file + uint64 recipientId = 2; + bool archived = 3; + optional uint32 pinnedOrder = 4; // will be displayed in ascending order + optional uint64 expirationTimerMs = 5; + optional uint64 muteUntilMs = 6; // INT64_MAX (2^63 - 1) = "always muted". + bool markedUnread = 7; + bool dontNotifyForMentionsIfMuted = 8; + ChatStyle style = 9; + uint32 expireTimerVersion = 10; } // @@ -330,785 +305,753 @@ message Chat { // - the presence of an admin key means this user is a call admin // message CallLink { - enum Restrictions { - UNKNOWN = 0; // Interpret as "Admin Approval" - NONE = 1; - ADMIN_APPROVAL = 2; - } + enum Restrictions { + UNKNOWN = 0; // Interpret as "Admin Approval" + NONE = 1; + ADMIN_APPROVAL = 2; + } - bytes rootKey = 1; - optional bytes adminKey = 2; // Only present if the user is an admin - string name = 3; - Restrictions restrictions = 4; - uint64 expirationMs = 5; + bytes rootKey = 1; + optional bytes adminKey = 2; // Only present if the user is an admin + string name = 3; + Restrictions restrictions = 4; + uint64 expirationMs = 5; } - message AdHocCall { - enum State { - UNKNOWN_STATE = 0; // Interpret as "Generic" - GENERIC = 1; - } + enum State { + UNKNOWN_STATE = 0; // Interpret as "Generic" + GENERIC = 1; + } - uint64 callId = 1; - // Refers to a `CallLink` recipient. - uint64 recipientId = 2; - State state = 3; - uint64 callTimestamp = 4; + uint64 callId = 1; + // Refers to a `CallLink` recipient. + uint64 recipientId = 2; + State state = 3; + uint64 callTimestamp = 4; } - message DistributionListItem { - // distribution ids are UUIDv4s. "My Story" is represented - // by an all-0 UUID (00000000-0000-0000-0000-000000000000). - bytes distributionId = 1; // distribution list ids are uuids + oneof item { + uint64 deletionTimestamp = 2; + DistributionList distributionList = 3; + } - // If unset, importers should skip the item entirely without showing an error. - oneof item { - uint64 deletionTimestamp = 2; - DistributionList distributionList = 3; - } + // distribution ids are UUIDv4s. "My Story" is represented + // by an all-0 UUID (00000000-0000-0000-0000-000000000000). + bytes distributionId = 1; // distribution list ids are uuids + + // If unset, importers should skip the item entirely without showing an error. } - message DistributionList { - enum PrivacyMode { - UNKNOWN = 0; // Interpret as "Only with" - ONLY_WITH = 1; - ALL_EXCEPT = 2; - ALL = 3; - } + enum PrivacyMode { + UNKNOWN = 0; // Interpret as "Only with" + ONLY_WITH = 1; + ALL_EXCEPT = 2; + ALL = 3; + } - string name = 1; - bool allowReplies = 2; - PrivacyMode privacyMode = 3; - repeated uint64 memberRecipientIds = 4; // generated recipient id + string name = 1; + bool allowReplies = 2; + PrivacyMode privacyMode = 3; + repeated uint64 memberRecipientIds = 4; // generated recipient id } - message ChatItem { - message IncomingMessageDetails { - uint64 dateReceived = 1; - optional uint64 dateServerSent = 2; - bool read = 3; - bool sealedSender = 4; - } + message IncomingMessageDetails { + uint64 dateReceived = 1; + optional uint64 dateServerSent = 2; + bool read = 3; + bool sealedSender = 4; + } + message OutgoingMessageDetails { + repeated SendStatus sendStatus = 1; + } + message DirectionlessMessageDetails { + } + oneof directionalDetails { + IncomingMessageDetails incoming = 8; + OutgoingMessageDetails outgoing = 9; + DirectionlessMessageDetails directionless = 10; + } + oneof item { + StandardMessage standardMessage = 11; + ContactMessage contactMessage = 12; + StickerMessage stickerMessage = 13; + RemoteDeletedMessage remoteDeletedMessage = 14; + ChatUpdateMessage updateMessage = 15; + PaymentNotification paymentNotification = 16; + GiftBadge giftBadge = 17; + ViewOnceMessage viewOnceMessage = 18; + DirectStoryReplyMessage directStoryReplyMessage = 19; // group story reply messages are not backed up + } - message OutgoingMessageDetails { - repeated SendStatus sendStatus = 1; - } + uint64 chatId = 1; // conversation id + uint64 authorId = 2; // recipient id + uint64 dateSent = 3; + optional uint64 expireStartDate = 4; // timestamp of when expiration timer started ticking down + optional uint64 expiresInMs = 5; // how long timer of message is (ms) + repeated ChatItem revisions = 6; // ordered from oldest to newest + bool sms = 7; - message DirectionlessMessageDetails { - } + // If unset, importers should skip this item without throwing an error. - uint64 chatId = 1; // conversation id - uint64 authorId = 2; // recipient id - uint64 dateSent = 3; - optional uint64 expireStartDate = 4; // timestamp of when expiration timer started ticking down - optional uint64 expiresInMs = 5; // how long timer of message is (ms) - repeated ChatItem revisions = 6; // ordered from oldest to newest - bool sms = 7; - - // If unset, importers should skip this item without throwing an error. - oneof directionalDetails { - IncomingMessageDetails incoming = 8; - OutgoingMessageDetails outgoing = 9; - DirectionlessMessageDetails directionless = 10; - } - - // If unset, importers should skip this item without throwing an error. - oneof item { - StandardMessage standardMessage = 11; - ContactMessage contactMessage = 12; - StickerMessage stickerMessage = 13; - RemoteDeletedMessage remoteDeletedMessage = 14; - ChatUpdateMessage updateMessage = 15; - PaymentNotification paymentNotification = 16; - GiftBadge giftBadge = 17; - ViewOnceMessage viewOnceMessage = 18; - DirectStoryReplyMessage directStoryReplyMessage = 19; // group story reply messages are not backed up - } + // If unset, importers should skip this item without throwing an error. } - message SendStatus { - message Pending {} - - message Sent { - bool sealedSender = 1; - } - - message Delivered { - bool sealedSender = 1; - } - - message Read { - bool sealedSender = 1; - } - - message Viewed { - bool sealedSender = 1; - } - - // e.g. user in group was blocked, so we skipped sending to them - message Skipped {} - - message Failed { - enum FailureReason { - UNKNOWN = 0; // A valid value -- could indicate a crash or lack of information - NETWORK = 1; - IDENTITY_KEY_MISMATCH = 2; - } - - FailureReason reason = 1; - } - - uint64 recipientId = 1; - uint64 timestamp = 2; // the time the status was last updated -- if from a receipt, it should be the sentTime of the receipt - - // If unset, importers should consider the status to be "pending" - oneof deliveryStatus { - Pending pending = 3; - Sent sent = 4; - Delivered delivered = 5; - Read read = 6; - Viewed viewed = 7; - Skipped skipped = 8; - Failed failed = 9; - } + // isEmpty +// footer was empty +message Sent { +bool sealedSender = 1; } +message Delivered { +bool sealedSender = 1; +} + +message Read { +bool sealedSender = 1; +} + +message Viewed { +bool sealedSender = 1; +} + +// e.g. user in group was blocked, so we skipped sending to them +message Skipped {} + +message Failed { +enum FailureReason { +UNKNOWN = 0; // A valid value -- could indicate a crash or lack of information +NETWORK = 1; +IDENTITY_KEY_MISMATCH = 2; +} + +FailureReason reason = 1; +} + +uint64 recipientId = 1; +uint64 timestamp = 2; // the time the status was last updated -- if from a receipt, it should be the sentTime of the receipt + +// If unset, importers should consider the status to be "pending" +oneof deliveryStatus { +Pending pending = 3; +Sent sent = 4; +Delivered delivered = 5; +Read read = 6; +Viewed viewed = 7; +Skipped skipped = 8; +Failed failed = 9; +} +} message Text { - string body = 1; - repeated BodyRange bodyRanges = 2; + string body = 1; + repeated BodyRange bodyRanges = 2; } message StandardMessage { - optional Quote quote = 1; - optional Text text = 2; - repeated MessageAttachment attachments = 3; - repeated LinkPreview linkPreview = 4; - optional FilePointer longText = 5; - repeated Reaction reactions = 6; + optional Quote quote = 1; + optional Text text = 2; + repeated MessageAttachment attachments = 3; + repeated LinkPreview linkPreview = 4; + optional FilePointer longText = 5; + repeated Reaction reactions = 6; } message ContactMessage { - ContactAttachment contact = 1; - repeated Reaction reactions = 2; + ContactAttachment contact = 1; + repeated Reaction reactions = 2; } message DirectStoryReplyMessage { - message TextReply { - Text text = 1; - FilePointer longText = 2; - } + message TextReply { + Text text = 1; + FilePointer longText = 2; + } + oneof reply { + TextReply textReply = 1; + string emoji = 2; + } - // If unset, importers should ignore the message without throwing an error. - oneof reply { - TextReply textReply = 1; - string emoji = 2; - } + // If unset, importers should ignore the message without throwing an error. - repeated Reaction reactions = 3; - reserved 4; // storySentTimestamp + repeated Reaction reactions = 3; + = 4; // storySentTimestamp } - message PaymentNotification { - message TransactionDetails { - message MobileCoinTxoIdentification { // Used to map to payments on the ledger - repeated bytes publicKey = 1; // for received transactions - repeated bytes keyImages = 2; // for sent transactions - } + message TransactionDetails { + message MobileCoinTxoIdentification { // Used to map to payments on the ledger + repeated bytes publicKey = 1; // for received transactions + repeated bytes keyImages = 2; // for sent transactions + } + message FailedTransaction { // Failed payments can't be synced from the ledger + enum FailureReason { + GENERIC = 0; // A valid value -- reason unknown + NETWORK = 1; + INSUFFICIENT_FUNDS = 2; + } + FailureReason reason = 1; + } + message Transaction { + enum Status { + INITIAL = 0; // A valid value -- state unconfirmed + SUBMITTED = 1; + SUCCESSFUL = 2; + } + Status status = 1; - message FailedTransaction { // Failed payments can't be synced from the ledger - enum FailureReason { - GENERIC = 0; // A valid value -- reason unknown - NETWORK = 1; - INSUFFICIENT_FUNDS = 2; - } - FailureReason reason = 1; - } + // This identification is used to map the payment table to the ledger + // and is likely required otherwise we may have issues reconciling with + // the ledger + MobileCoinTxoIdentification mobileCoinIdentification = 2; + optional uint64 timestamp = 3; + optional uint64 blockIndex = 4; + optional uint64 blockTimestamp = 5; + optional bytes transaction = 6; // mobile coin blobs + optional bytes receipt = 7; // mobile coin blobs + } + oneof payment { + Transaction transaction = 1; + FailedTransaction failedTransaction = 2; + } - message Transaction { - enum Status { - INITIAL = 0; // A valid value -- state unconfirmed - SUBMITTED = 1; - SUCCESSFUL = 2; - } - Status status = 1; - - // This identification is used to map the payment table to the ledger - // and is likely required otherwise we may have issues reconciling with - // the ledger - MobileCoinTxoIdentification mobileCoinIdentification = 2; - optional uint64 timestamp = 3; - optional uint64 blockIndex = 4; - optional uint64 blockTimestamp = 5; - optional bytes transaction = 6; // mobile coin blobs - optional bytes receipt = 7; // mobile coin blobs - } - - // If unset, importers should treat the transaction as successful with no metadata. - oneof payment { - Transaction transaction = 1; - FailedTransaction failedTransaction = 2; - } - } - - optional string amountMob = 1; // stored as a decimal string, e.g. 1.00001 - optional string feeMob = 2; // stored as a decimal string, e.g. 1.00001 - optional string note = 3; - TransactionDetails transactionDetails = 4; + // If unset, importers should treat the transaction as successful with no metadata. + } + optional string amountMob = 1; // stored as a decimal string, e.g. 1.00001 + optional string feeMob = 2; // stored as a decimal string, e.g. 1.00001 + optional string note = 3; + TransactionDetails transactionDetails = 4; } - message GiftBadge { - enum State { - UNOPENED = 0; // A valid state - OPENED = 1; - REDEEMED = 2; - FAILED = 3; - } + enum State { + UNOPENED = 0; // A valid state + OPENED = 1; + REDEEMED = 2; + FAILED = 3; + } - bytes receiptCredentialPresentation = 1; - State state = 2; + bytes receiptCredentialPresentation = 1; + State state = 2; } - message ViewOnceMessage { - // Will be null for viewed messages - MessageAttachment attachment = 1; - repeated Reaction reactions = 2; + // Will be null for viewed messages + MessageAttachment attachment = 1; + repeated Reaction reactions = 2; } message ContactAttachment { - message Name { - string givenName = 1; - string familyName = 2; - string prefix = 3; - string suffix = 4; - string middleName = 5; - string nickname = 6; - } + message Name { + string givenName = 1; + string familyName = 2; + string prefix = 3; + string suffix = 4; + string middleName = 5; + string nickname = 6; + } + message Phone { + enum Type { + UNKNOWN = 0; // Interpret as "Home" + HOME = 1; + MOBILE = 2; + WORK = 3; + CUSTOM = 4; + } + string value = 1; + Type type = 2; + string label = 3; + } + message Email { + enum Type { + UNKNOWN = 0; // Intepret as "Home" + HOME = 1; + MOBILE = 2; + WORK = 3; + CUSTOM = 4; + } + string value = 1; + Type type = 2; + string label = 3; + } + message PostalAddress { + enum Type { + UNKNOWN = 0; // Interpret as "Home" + HOME = 1; + WORK = 2; + CUSTOM = 3; + } - message Phone { - enum Type { - UNKNOWN = 0; // Interpret as "Home" - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - string value = 1; - Type type = 2; - string label = 3; - } - - message Email { - enum Type { - UNKNOWN = 0; // Intepret as "Home" - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - string value = 1; - Type type = 2; - string label = 3; - } - - message PostalAddress { - enum Type { - UNKNOWN = 0; // Interpret as "Home" - HOME = 1; - WORK = 2; - CUSTOM = 3; - } - - Type type = 1; - string label = 2; - string street = 3; - string pobox = 4; - string neighborhood = 5; - string city = 6; - string region = 7; - string postcode = 8; - string country = 9; - } - - optional Name name = 1; - repeated Phone number = 3; - repeated Email email = 4; - repeated PostalAddress address = 5; - optional FilePointer avatar = 6; - string organization = 7; + Type type = 1; + string label = 2; + string street = 3; + string pobox = 4; + string neighborhood = 5; + string city = 6; + string region = 7; + string postcode = 8; + string country = 9; + } + optional Name name = 1; + repeated Phone number = 3; + repeated Email email = 4; + repeated PostalAddress address = 5; + optional FilePointer avatar = 6; + string organization = 7; } - message StickerMessage { - Sticker sticker = 1; - repeated Reaction reactions = 2; + Sticker sticker = 1; + repeated Reaction reactions = 2; } -// Tombstone for remote delete -message RemoteDeletedMessage {} - +// isEmpty message Sticker { - bytes packId = 1; - bytes packKey = 2; - uint32 stickerId = 3; - optional string emoji = 4; - // Stickers are uploaded to be sent as attachments; we also - // back them up as normal attachments when they are in messages. - // DO NOT treat this as the definitive source of a sticker in - // an installed StickerPack that shares the same packId. - FilePointer data = 5; + bytes packId = 1; + bytes packKey = 2; + uint32 stickerId = 3; + optional string emoji = 4; + // Stickers are uploaded to be sent as attachments; we also + // back them up as normal attachments when they are in messages. + // DO NOT treat this as the definitive source of a sticker in + // an installed StickerPack that shares the same packId. + FilePointer data = 5; } message LinkPreview { - string url = 1; - optional string title = 2; - optional FilePointer image = 3; - optional string description = 4; - optional uint64 date = 5; + string url = 1; + optional string title = 2; + optional FilePointer image = 3; + optional string description = 4; + optional uint64 date = 5; } // A FilePointer on a message that has additional // metadata that applies only to message attachments. message MessageAttachment { - // Similar to SignalService.AttachmentPointer.Flags, - // but explicitly mutually exclusive. Note the different raw values - // (non-zero starting values are not supported in proto3.) - enum Flag { - NONE = 0; // A valid value -- no flag applied - VOICE_MESSAGE = 1; - BORDERLESS = 2; - GIF = 3; - } + enum Flag { + NONE = 0; // A valid value -- no flag applied + VOICE_MESSAGE = 1; + BORDERLESS = 2; + GIF = 3; + } - FilePointer pointer = 1; - Flag flag = 2; - bool wasDownloaded = 3; - // Cross-client identifier for this attachment among all attachments on the - // owning message. See: SignalService.AttachmentPointer.clientUuid. - optional bytes clientUuid = 4; + // Similar to SignalService.AttachmentPointer.Flags, + // but explicitly mutually exclusive. Note the different raw values + // (non-zero starting values are not supported in proto3.) + + FilePointer pointer = 1; + Flag flag = 2; + bool wasDownloaded = 3; + // Cross-client identifier for this attachment among all attachments on the + // owning message. See: SignalService.AttachmentPointer.clientUuid. + optional bytes clientUuid = 4; } - message FilePointer { - // References attachments in the backup (media) storage tier. - message BackupLocator { - string mediaName = 1; - // If present, the cdn number of the succesful upload. - // If empty/0, may still have been uploaded, and clients - // can discover the cdn number via the list endpoint. - optional uint32 cdnNumber = 2; - bytes key = 3; - bytes digest = 4; - uint32 size = 5; - // Fallback in case backup tier upload failed. - optional string transitCdnKey = 6; - optional uint32 transitCdnNumber = 7; - } + message BackupLocator { + string mediaName = 1; + // If present, the cdn number of the succesful upload. + // If empty/0, may still have been uploaded, and clients + // can discover the cdn number via the list endpoint. + optional uint32 cdnNumber = 2; + bytes key = 3; + bytes digest = 4; + uint32 size = 5; + // Fallback in case backup tier upload failed. + optional string transitCdnKey = 6; + optional uint32 transitCdnNumber = 7; + } + message AttachmentLocator { + string cdnKey = 1; + uint32 cdnNumber = 2; + optional uint64 uploadTimestamp = 3; + bytes key = 4; + bytes digest = 5; + uint32 size = 6; + } + message InvalidAttachmentLocator { + } + oneof locator { + BackupLocator backupLocator = 1; + AttachmentLocator attachmentLocator = 2; + InvalidAttachmentLocator invalidAttachmentLocator = 3; + } - // References attachments in the transit storage tier. - // May be downloaded or not when the backup is generated; - // primarily for free-tier users who cannot copy the - // attachments to the backup (media) storage tier. - message AttachmentLocator { - string cdnKey = 1; - uint32 cdnNumber = 2; - optional uint64 uploadTimestamp = 3; - bytes key = 4; - bytes digest = 5; - uint32 size = 6; - } + // References attachments in the backup (media) storage tier. - // References attachments that are invalid in such a way where download - // cannot be attempted. Could range from missing digests to missing - // CDN keys or anything else that makes download attempts impossible. - // This serves as a 'tombstone' so that the UX can show that an attachment - // did exist, but for whatever reason it's not retrievable. - message InvalidAttachmentLocator { - } + // References attachments in the transit storage tier. + // May be downloaded or not when the backup is generated; + // primarily for free-tier users who cannot copy the + // attachments to the backup (media) storage tier. - // If unset, importers should consider it to be an InvalidAttachmentLocator without throwing an error. - oneof locator { - BackupLocator backupLocator = 1; - AttachmentLocator attachmentLocator = 2; - InvalidAttachmentLocator invalidAttachmentLocator = 3; - } + // References attachments that are invalid in such a way where download + // cannot be attempted. Could range from missing digests to missing + // CDN keys or anything else that makes download attempts impossible. + // This serves as a 'tombstone' so that the UX can show that an attachment + // did exist, but for whatever reason it's not retrievable. - optional string contentType = 4; - optional bytes incrementalMac = 5; - optional uint32 incrementalMacChunkSize = 6; - optional string fileName = 7; - optional uint32 width = 8; - optional uint32 height = 9; - optional string caption = 10; - optional string blurHash = 11; + // If unset, importers should consider it to be an InvalidAttachmentLocator without throwing an error. + + optional string contentType = 4; + optional bytes incrementalMac = 5; + optional uint32 incrementalMacChunkSize = 6; + optional string fileName = 7; + optional uint32 width = 8; + optional uint32 height = 9; + optional string caption = 10; + optional string blurHash = 11; } - message Quote { - enum Type { - UNKNOWN = 0; // Interpret as "Normal" - NORMAL = 1; - GIFT_BADGE = 2; - VIEW_ONCE = 3; - } + enum Type { + UNKNOWN = 0; // Interpret as "Normal" + NORMAL = 1; + GIFT_BADGE = 2; + VIEW_ONCE = 3; + } + message QuotedAttachment { + optional string contentType = 1; + optional string fileName = 2; + optional MessageAttachment thumbnail = 3; + } - message QuotedAttachment { - optional string contentType = 1; - optional string fileName = 2; - optional MessageAttachment thumbnail = 3; - } - - optional uint64 targetSentTimestamp = 1; // null if the target message could not be found at time of quote insert - uint64 authorId = 2; - optional Text text = 3; - repeated QuotedAttachment attachments = 4; - Type type = 5; + optional uint64 targetSentTimestamp = 1; // null if the target message could not be found at time of quote insert + uint64 authorId = 2; + optional Text text = 3; + repeated QuotedAttachment attachments = 4; + Type type = 5; } - message BodyRange { - enum Style { - NONE = 0; // Importers should ignore the body range without throwing an error. - BOLD = 1; - ITALIC = 2; - SPOILER = 3; - STRIKETHROUGH = 4; - MONOSPACE = 5; - } + enum Style { + NONE = 0; // Importers should ignore the body range without throwing an error. + BOLD = 1; + ITALIC = 2; + SPOILER = 3; + STRIKETHROUGH = 4; + MONOSPACE = 5; + } + oneof associatedValue { + bytes mentionAci = 3; + Style style = 4; + } - // 'start' and 'length' are measured in UTF-16 code units. - // They may refer to offsets in a longText attachment. - uint32 start = 1; - uint32 length = 2; + // 'start' and 'length' are measured in UTF-16 code units. + // They may refer to offsets in a longText attachment. + uint32 start = 1; + uint32 length = 2; - // If unset, importers should ignore the body range without throwing an error. - oneof associatedValue { - bytes mentionAci = 3; - Style style = 4; - } + // If unset, importers should ignore the body range without throwing an error. } - message Reaction { - string emoji = 1; - uint64 authorId = 2; - uint64 sentTimestamp = 3; - // A higher sort order means that a reaction is more recent. Some clients may export this as - // incrementing numbers (e.g. 1, 2, 3), others as timestamps. - uint64 sortOrder = 4; + string emoji = 1; + uint64 authorId = 2; + uint64 sentTimestamp = 3; + // A higher sort order means that a reaction is more recent. Some clients may export this as + // incrementing numbers (e.g. 1, 2, 3), others as timestamps. + uint64 sortOrder = 4; } message ChatUpdateMessage { - // If unset, importers should ignore the update message without throwing an error. - oneof update { - SimpleChatUpdate simpleUpdate = 1; - GroupChangeChatUpdate groupChange = 2; - ExpirationTimerChatUpdate expirationTimerChange = 3; - ProfileChangeChatUpdate profileChange = 4; - ThreadMergeChatUpdate threadMerge = 5; - SessionSwitchoverChatUpdate sessionSwitchover = 6; - IndividualCall individualCall = 7; - GroupCall groupCall = 8; - LearnedProfileChatUpdate learnedProfileChange = 9; - } -} + oneof update { + SimpleChatUpdate simpleUpdate = 1; + GroupChangeChatUpdate groupChange = 2; + ExpirationTimerChatUpdate expirationTimerChange = 3; + ProfileChangeChatUpdate profileChange = 4; + ThreadMergeChatUpdate threadMerge = 5; + SessionSwitchoverChatUpdate sessionSwitchover = 6; + IndividualCall individualCall = 7; + GroupCall groupCall = 8; + LearnedProfileChatUpdate learnedProfileChange = 9; + } + // If unset, importers should ignore the update message without throwing an error. +} message IndividualCall { - enum Type { - UNKNOWN_TYPE = 0; // Interpret as "Audio call" - AUDIO_CALL = 1; - VIDEO_CALL = 2; - } + enum Type { + UNKNOWN_TYPE = 0; // Interpret as "Audio call" + AUDIO_CALL = 1; + VIDEO_CALL = 2; + } + enum Direction { + UNKNOWN_DIRECTION = 0; // Interpret as "Incoming" + INCOMING = 1; + OUTGOING = 2; + } + enum State { + UNKNOWN_STATE = 0; // Interpret as "Accepted" + ACCEPTED = 1; + NOT_ACCEPTED = 2; + // An incoming call that is no longer ongoing, which we neither accepted + // not actively declined. For example, it expired, was canceled by the + // sender, or was rejected due to being in another call. + MISSED = 3; + // We auto-declined an incoming call due to a notification profile. + MISSED_NOTIFICATION_PROFILE = 4; + } - enum Direction { - UNKNOWN_DIRECTION = 0; // Interpret as "Incoming" - INCOMING = 1; - OUTGOING = 2; - } - - enum State { - UNKNOWN_STATE = 0; // Interpret as "Accepted" - ACCEPTED = 1; - NOT_ACCEPTED = 2; - // An incoming call that is no longer ongoing, which we neither accepted - // not actively declined. For example, it expired, was canceled by the - // sender, or was rejected due to being in another call. - MISSED = 3; - // We auto-declined an incoming call due to a notification profile. - MISSED_NOTIFICATION_PROFILE = 4; - } - - optional uint64 callId = 1; - Type type = 2; - Direction direction = 3; - State state = 4; - uint64 startedCallTimestamp = 5; - bool read = 6; + optional uint64 callId = 1; + Type type = 2; + Direction direction = 3; + State state = 4; + uint64 startedCallTimestamp = 5; + bool read = 6; } - message GroupCall { - enum State { - UNKNOWN_STATE = 0; // Interpret as "Generic" - // A group call was started without ringing. - GENERIC = 1; - // We joined a group call that was started without ringing. - JOINED = 2; - // An incoming group call is actively ringing. - RINGING = 3; - // We accepted an incoming group ring. - ACCEPTED = 4; - // We declined an incoming group ring. - DECLINED = 5; - // We missed an incoming group ring, for example because it expired. - MISSED = 6; - // We auto-declined an incoming group ring due to a notification profile. - MISSED_NOTIFICATION_PROFILE = 7; - // An outgoing ring was started. We don't track any state for outgoing rings - // beyond that they started. - OUTGOING_RING = 8; - } + enum State { + UNKNOWN_STATE = 0; // Interpret as "Generic" + // A group call was started without ringing. + GENERIC = 1; + // We joined a group call that was started without ringing. + JOINED = 2; + // An incoming group call is actively ringing. + RINGING = 3; + // We accepted an incoming group ring. + ACCEPTED = 4; + // We declined an incoming group ring. + DECLINED = 5; + // We missed an incoming group ring, for example because it expired. + MISSED = 6; + // We auto-declined an incoming group ring due to a notification profile. + MISSED_NOTIFICATION_PROFILE = 7; + // An outgoing ring was started. We don't track any state for outgoing rings + // beyond that they started. + OUTGOING_RING = 8; + } - optional uint64 callId = 1; - State state = 2; - optional uint64 ringerRecipientId = 3; - optional uint64 startedCallRecipientId = 4; - uint64 startedCallTimestamp = 5; - optional uint64 endedCallTimestamp = 6; // The time the call ended. - bool read = 7; + optional uint64 callId = 1; + State state = 2; + optional uint64 ringerRecipientId = 3; + optional uint64 startedCallRecipientId = 4; + uint64 startedCallTimestamp = 5; + optional uint64 endedCallTimestamp = 6; // The time the call ended. + bool read = 7; } - message SimpleChatUpdate { - enum Type { - UNKNOWN = 0; // Importers should skip the update without throwing an error. - JOINED_SIGNAL = 1; - IDENTITY_UPDATE = 2; - IDENTITY_VERIFIED = 3; - IDENTITY_DEFAULT = 4; // marking as unverified - CHANGE_NUMBER = 5; - RELEASE_CHANNEL_DONATION_REQUEST = 6; - END_SESSION = 7; - CHAT_SESSION_REFRESH = 8; - BAD_DECRYPT = 9; - PAYMENTS_ACTIVATED = 10; - PAYMENT_ACTIVATION_REQUEST = 11; - UNSUPPORTED_PROTOCOL_MESSAGE = 12; - REPORTED_SPAM = 13; - BLOCKED = 14; - UNBLOCKED = 15; - MESSAGE_REQUEST_ACCEPTED = 16; - } + enum Type { + UNKNOWN = 0; // Importers should skip the update without throwing an error. + JOINED_SIGNAL = 1; + IDENTITY_UPDATE = 2; + IDENTITY_VERIFIED = 3; + IDENTITY_DEFAULT = 4; // marking as unverified + CHANGE_NUMBER = 5; + RELEASE_CHANNEL_DONATION_REQUEST = 6; + END_SESSION = 7; + CHAT_SESSION_REFRESH = 8; + BAD_DECRYPT = 9; + PAYMENTS_ACTIVATED = 10; + PAYMENT_ACTIVATION_REQUEST = 11; + UNSUPPORTED_PROTOCOL_MESSAGE = 12; + REPORTED_SPAM = 13; + BLOCKED = 14; + UNBLOCKED = 15; + MESSAGE_REQUEST_ACCEPTED = 16; + } - Type type = 1; + Type type = 1; } - // For 1:1 chat updates only. // For group thread updates use GroupExpirationTimerUpdate. message ExpirationTimerChatUpdate { - uint64 expiresInMs = 1; // 0 means the expiration timer was disabled + uint64 expiresInMs = 1; // 0 means the expiration timer was disabled } message ProfileChangeChatUpdate { - string previousName = 1; - string newName = 2; + string previousName = 1; + string newName = 2; } message LearnedProfileChatUpdate { - // If unset, importers should consider the previous name to be an empty string. - oneof previousName { - uint64 e164 = 1; - string username = 2; - } -} + oneof previousName { + uint64 e164 = 1; + string username = 2; + } + // If unset, importers should consider the previous name to be an empty string. +} message ThreadMergeChatUpdate { - uint64 previousE164 = 1; + uint64 previousE164 = 1; } message SessionSwitchoverChatUpdate { - uint64 e164 = 1; + uint64 e164 = 1; } message GroupChangeChatUpdate { - message Update { - // If unset, importers should consider it to be a GenericGroupUpdate with unset updaterAci - oneof update { - GenericGroupUpdate genericGroupUpdate = 1; - GroupCreationUpdate groupCreationUpdate = 2; - GroupNameUpdate groupNameUpdate = 3; - GroupAvatarUpdate groupAvatarUpdate = 4; - GroupDescriptionUpdate groupDescriptionUpdate = 5; - GroupMembershipAccessLevelChangeUpdate groupMembershipAccessLevelChangeUpdate = 6; - GroupAttributesAccessLevelChangeUpdate groupAttributesAccessLevelChangeUpdate = 7; - GroupAnnouncementOnlyChangeUpdate groupAnnouncementOnlyChangeUpdate = 8; - GroupAdminStatusUpdate groupAdminStatusUpdate = 9; - GroupMemberLeftUpdate groupMemberLeftUpdate = 10; - GroupMemberRemovedUpdate groupMemberRemovedUpdate = 11; - SelfInvitedToGroupUpdate selfInvitedToGroupUpdate = 12; - SelfInvitedOtherUserToGroupUpdate selfInvitedOtherUserToGroupUpdate = 13; - GroupUnknownInviteeUpdate groupUnknownInviteeUpdate = 14; - GroupInvitationAcceptedUpdate groupInvitationAcceptedUpdate = 15; - GroupInvitationDeclinedUpdate groupInvitationDeclinedUpdate = 16; - GroupMemberJoinedUpdate groupMemberJoinedUpdate = 17; - GroupMemberAddedUpdate groupMemberAddedUpdate = 18; - GroupSelfInvitationRevokedUpdate groupSelfInvitationRevokedUpdate = 19; - GroupInvitationRevokedUpdate groupInvitationRevokedUpdate = 20; - GroupJoinRequestUpdate groupJoinRequestUpdate = 21; - GroupJoinRequestApprovalUpdate groupJoinRequestApprovalUpdate = 22; - GroupJoinRequestCanceledUpdate groupJoinRequestCanceledUpdate = 23; - GroupInviteLinkResetUpdate groupInviteLinkResetUpdate = 24; - GroupInviteLinkEnabledUpdate groupInviteLinkEnabledUpdate = 25; - GroupInviteLinkAdminApprovalUpdate groupInviteLinkAdminApprovalUpdate = 26; - GroupInviteLinkDisabledUpdate groupInviteLinkDisabledUpdate = 27; - GroupMemberJoinedByLinkUpdate groupMemberJoinedByLinkUpdate = 28; - GroupV2MigrationUpdate groupV2MigrationUpdate = 29; - GroupV2MigrationSelfInvitedUpdate groupV2MigrationSelfInvitedUpdate = 30; - GroupV2MigrationInvitedMembersUpdate groupV2MigrationInvitedMembersUpdate = 31; - GroupV2MigrationDroppedMembersUpdate groupV2MigrationDroppedMembersUpdate = 32; - GroupSequenceOfRequestsAndCancelsUpdate groupSequenceOfRequestsAndCancelsUpdate = 33; - GroupExpirationTimerUpdate groupExpirationTimerUpdate = 34; - } - } + message Update { + oneof update { + GenericGroupUpdate genericGroupUpdate = 1; + GroupCreationUpdate groupCreationUpdate = 2; + GroupNameUpdate groupNameUpdate = 3; + GroupAvatarUpdate groupAvatarUpdate = 4; + GroupDescriptionUpdate groupDescriptionUpdate = 5; + GroupMembershipAccessLevelChangeUpdate groupMembershipAccessLevelChangeUpdate = 6; + GroupAttributesAccessLevelChangeUpdate groupAttributesAccessLevelChangeUpdate = 7; + GroupAnnouncementOnlyChangeUpdate groupAnnouncementOnlyChangeUpdate = 8; + GroupAdminStatusUpdate groupAdminStatusUpdate = 9; + GroupMemberLeftUpdate groupMemberLeftUpdate = 10; + GroupMemberRemovedUpdate groupMemberRemovedUpdate = 11; + SelfInvitedToGroupUpdate selfInvitedToGroupUpdate = 12; + SelfInvitedOtherUserToGroupUpdate selfInvitedOtherUserToGroupUpdate = 13; + GroupUnknownInviteeUpdate groupUnknownInviteeUpdate = 14; + GroupInvitationAcceptedUpdate groupInvitationAcceptedUpdate = 15; + GroupInvitationDeclinedUpdate groupInvitationDeclinedUpdate = 16; + GroupMemberJoinedUpdate groupMemberJoinedUpdate = 17; + GroupMemberAddedUpdate groupMemberAddedUpdate = 18; + GroupSelfInvitationRevokedUpdate groupSelfInvitationRevokedUpdate = 19; + GroupInvitationRevokedUpdate groupInvitationRevokedUpdate = 20; + GroupJoinRequestUpdate groupJoinRequestUpdate = 21; + GroupJoinRequestApprovalUpdate groupJoinRequestApprovalUpdate = 22; + GroupJoinRequestCanceledUpdate groupJoinRequestCanceledUpdate = 23; + GroupInviteLinkResetUpdate groupInviteLinkResetUpdate = 24; + GroupInviteLinkEnabledUpdate groupInviteLinkEnabledUpdate = 25; + GroupInviteLinkAdminApprovalUpdate groupInviteLinkAdminApprovalUpdate = 26; + GroupInviteLinkDisabledUpdate groupInviteLinkDisabledUpdate = 27; + GroupMemberJoinedByLinkUpdate groupMemberJoinedByLinkUpdate = 28; + GroupV2MigrationUpdate groupV2MigrationUpdate = 29; + GroupV2MigrationSelfInvitedUpdate groupV2MigrationSelfInvitedUpdate = 30; + GroupV2MigrationInvitedMembersUpdate groupV2MigrationInvitedMembersUpdate = 31; + GroupV2MigrationDroppedMembersUpdate groupV2MigrationDroppedMembersUpdate = 32; + GroupSequenceOfRequestsAndCancelsUpdate groupSequenceOfRequestsAndCancelsUpdate = 33; + GroupExpirationTimerUpdate groupExpirationTimerUpdate = 34; + } - // Must be one or more; all updates batched together came from - // a single batched group state update. - repeated Update updates = 1; + // If unset, importers should consider it to be a GenericGroupUpdate with unset updaterAci + } + // Must be one or more; all updates batched together came from + // a single batched group state update. + repeated Update updates = 1; } - message GenericGroupUpdate { - optional bytes updaterAci = 1; + optional bytes updaterAci = 1; } message GroupCreationUpdate { - optional bytes updaterAci = 1; + optional bytes updaterAci = 1; } message GroupNameUpdate { - optional bytes updaterAci = 1; - // Null value means the group name was removed. - optional string newGroupName = 2; + optional bytes updaterAci = 1; + // Null value means the group name was removed. + optional string newGroupName = 2; } message GroupAvatarUpdate { - optional bytes updaterAci = 1; - bool wasRemoved = 2; + optional bytes updaterAci = 1; + bool wasRemoved = 2; } message GroupDescriptionUpdate { - optional bytes updaterAci = 1; - // Null value means the group description was removed. - optional string newDescription = 2; + optional bytes updaterAci = 1; + // Null value means the group description was removed. + optional string newDescription = 2; } enum GroupV2AccessLevel { - UNKNOWN = 0; // Interpret as "Unsatisfiable" - ANY = 1; - MEMBER = 2; - ADMINISTRATOR = 3; - UNSATISFIABLE = 4; + UNKNOWN = 0; // Interpret as "Unsatisfiable" + ANY = 1; + MEMBER = 2; + ADMINISTRATOR = 3; + UNSATISFIABLE = 4; } message GroupMembershipAccessLevelChangeUpdate { - optional bytes updaterAci = 1; - GroupV2AccessLevel accessLevel = 2; + optional bytes updaterAci = 1; + GroupV2AccessLevel accessLevel = 2; } message GroupAttributesAccessLevelChangeUpdate { - optional bytes updaterAci = 1; - GroupV2AccessLevel accessLevel = 2; + optional bytes updaterAci = 1; + GroupV2AccessLevel accessLevel = 2; } message GroupAnnouncementOnlyChangeUpdate { - optional bytes updaterAci = 1; - bool isAnnouncementOnly = 2; + optional bytes updaterAci = 1; + bool isAnnouncementOnly = 2; } message GroupAdminStatusUpdate { - optional bytes updaterAci = 1; - // The aci who had admin status granted or revoked. - bytes memberAci = 2; - bool wasAdminStatusGranted = 3; + optional bytes updaterAci = 1; + // The aci who had admin status granted or revoked. + bytes memberAci = 2; + bool wasAdminStatusGranted = 3; } message GroupMemberLeftUpdate { - bytes aci = 1; + bytes aci = 1; } message GroupMemberRemovedUpdate { - optional bytes removerAci = 1; - bytes removedAci = 2; + optional bytes removerAci = 1; + bytes removedAci = 2; } message SelfInvitedToGroupUpdate { - optional bytes inviterAci = 1; + optional bytes inviterAci = 1; } message SelfInvitedOtherUserToGroupUpdate { - // If no invitee id available, use GroupUnknownInviteeUpdate - bytes inviteeServiceId = 1; + // If no invitee id available, use GroupUnknownInviteeUpdate + bytes inviteeServiceId = 1; } message GroupUnknownInviteeUpdate { - // Can be the self user. - optional bytes inviterAci = 1; - uint32 inviteeCount = 2; + // Can be the self user. + optional bytes inviterAci = 1; + uint32 inviteeCount = 2; } message GroupInvitationAcceptedUpdate { - optional bytes inviterAci = 1; - bytes newMemberAci = 2; + optional bytes inviterAci = 1; + bytes newMemberAci = 2; } message GroupInvitationDeclinedUpdate { - optional bytes inviterAci = 1; - // Note: if invited by pni, just set inviteeAci to nil. - optional bytes inviteeAci = 2; + optional bytes inviterAci = 1; + // Note: if invited by pni, just set inviteeAci to nil. + optional bytes inviteeAci = 2; } message GroupMemberJoinedUpdate { - bytes newMemberAci = 1; + bytes newMemberAci = 1; } message GroupMemberAddedUpdate { - optional bytes updaterAci = 1; - bytes newMemberAci = 2; - bool hadOpenInvitation = 3; - // If hadOpenInvitation is true, optionally include aci of the inviter. - optional bytes inviterAci = 4; + optional bytes updaterAci = 1; + bytes newMemberAci = 2; + bool hadOpenInvitation = 3; + // If hadOpenInvitation is true, optionally include aci of the inviter. + optional bytes inviterAci = 4; } // An invitation to self was revoked. message GroupSelfInvitationRevokedUpdate { - optional bytes revokerAci = 1; + optional bytes revokerAci = 1; } // These invitees should never be the local user. // Use GroupSelfInvitationRevokedUpdate in those cases. // The inviter or updater can be the local user. message GroupInvitationRevokedUpdate { - message Invitee { - optional bytes inviterAci = 1; - // Prefer to use aci over pni. No need to set - // pni if aci is set. Both can be missing. - optional bytes inviteeAci = 2; - optional bytes inviteePni = 3; - } + message Invitee { + optional bytes inviterAci = 1; + // Prefer to use aci over pni. No need to set + // pni if aci is set. Both can be missing. + optional bytes inviteeAci = 2; + optional bytes inviteePni = 3; + } - // The member that revoked the invite(s), not the inviter! - // Assumed to be an admin (at the time, may no longer be an - // admin or even a member). - optional bytes updaterAci = 1; - repeated Invitee invitees = 2; + // The member that revoked the invite(s), not the inviter! + // Assumed to be an admin (at the time, may no longer be an + // admin or even a member). + optional bytes updaterAci = 1; + repeated Invitee invitees = 2; } - message GroupJoinRequestUpdate { - bytes requestorAci = 1; + bytes requestorAci = 1; } message GroupJoinRequestApprovalUpdate { - bytes requestorAci = 1; - // The aci that approved or rejected the request. - optional bytes updaterAci = 2; - bool wasApproved = 3; + bytes requestorAci = 1; + // The aci that approved or rejected the request. + optional bytes updaterAci = 2; + bool wasApproved = 3; } message GroupJoinRequestCanceledUpdate { - bytes requestorAci = 1; + bytes requestorAci = 1; } // A single requestor has requested to join and cancelled @@ -1118,198 +1061,189 @@ message GroupJoinRequestCanceledUpdate { // after, it will be a separate GroupJoinRequestUpdate, either // in the same frame or in a subsequent frame. message GroupSequenceOfRequestsAndCancelsUpdate { - bytes requestorAci = 1; - uint32 count = 2; + bytes requestorAci = 1; + uint32 count = 2; } message GroupInviteLinkResetUpdate { - optional bytes updaterAci = 1; + optional bytes updaterAci = 1; } message GroupInviteLinkEnabledUpdate { - optional bytes updaterAci = 1; - bool linkRequiresAdminApproval = 2; + optional bytes updaterAci = 1; + bool linkRequiresAdminApproval = 2; } message GroupInviteLinkAdminApprovalUpdate { - optional bytes updaterAci = 1; - bool linkRequiresAdminApproval = 2; + optional bytes updaterAci = 1; + bool linkRequiresAdminApproval = 2; } message GroupInviteLinkDisabledUpdate { - optional bytes updaterAci = 1; + optional bytes updaterAci = 1; } message GroupMemberJoinedByLinkUpdate { - bytes newMemberAci = 1; + bytes newMemberAci = 1; } -// A gv1->gv2 migration occurred. -message GroupV2MigrationUpdate {} - -// Another user migrated gv1->gv2 but was unable to add -// the local user and invited them instead. -message GroupV2MigrationSelfInvitedUpdate {} - +// isEmpty +// isEmpty // The local user migrated gv1->gv2 but was unable to // add some members and invited them instead. // (Happens if we don't have the invitee's profile key) message GroupV2MigrationInvitedMembersUpdate { - uint32 invitedMembersCount = 1; + uint32 invitedMembersCount = 1; } // The local user migrated gv1->gv2 but was unable to // add or invite some members and dropped them instead. // (Happens for e164 members where we don't have an aci). message GroupV2MigrationDroppedMembersUpdate { - uint32 droppedMembersCount = 1; + uint32 droppedMembersCount = 1; } // For 1:1 timer updates, use ExpirationTimerChatUpdate. message GroupExpirationTimerUpdate { - uint64 expiresInMs = 1; // 0 means the expiration timer was disabled - optional bytes updaterAci = 2; + uint64 expiresInMs = 1; // 0 means the expiration timer was disabled + optional bytes updaterAci = 2; } message StickerPack { - bytes packId = 1; - bytes packKey = 2; + bytes packId = 1; + bytes packKey = 2; } message ChatStyle { - message Gradient { - uint32 angle = 1; // degrees - repeated fixed32 colors = 2; // 0xAARRGGBB - repeated float positions = 3; // percent from 0 to 1 - } + message Gradient { + uint32 angle = 1; // degrees + repeated fixed32 colors = 2; // 0xAARRGGBB + repeated float positions = 3; // percent from 0 to 1 + } + message CustomChatColor { + oneof color { + fixed32 solid = 2; // 0xAARRGGBB + Gradient gradient = 3; + } + uint64 id = 1; - message CustomChatColor { - uint64 id = 1; + // If unset, use the default chat color + } + message AutomaticBubbleColor { + } + enum WallpaperPreset { + UNKNOWN_WALLPAPER_PRESET = 0; // Interpret as the wallpaper being unset + SOLID_BLUSH = 1; + SOLID_COPPER = 2; + SOLID_DUST = 3; + SOLID_CELADON = 4; + SOLID_RAINFOREST = 5; + SOLID_PACIFIC = 6; + SOLID_FROST = 7; + SOLID_NAVY = 8; + SOLID_LILAC = 9; + SOLID_PINK = 10; + SOLID_EGGPLANT = 11; + SOLID_SILVER = 12; + GRADIENT_SUNSET = 13; + GRADIENT_NOIR = 14; + GRADIENT_HEATMAP = 15; + GRADIENT_AQUA = 16; + GRADIENT_IRIDESCENT = 17; + GRADIENT_MONSTERA = 18; + GRADIENT_BLISS = 19; + GRADIENT_SKY = 20; + GRADIENT_PEACH = 21; + } + enum BubbleColorPreset { + UNKNOWN_BUBBLE_COLOR_PRESET = 0; // Interpret as the user's default chat bubble color + SOLID_ULTRAMARINE = 1; + SOLID_CRIMSON = 2; + SOLID_VERMILION = 3; + SOLID_BURLAP = 4; + SOLID_FOREST = 5; + SOLID_WINTERGREEN = 6; + SOLID_TEAL = 7; + SOLID_BLUE = 8; + SOLID_INDIGO = 9; + SOLID_VIOLET = 10; + SOLID_PLUM = 11; + SOLID_TAUPE = 12; + SOLID_STEEL = 13; + GRADIENT_EMBER = 14; + GRADIENT_MIDNIGHT = 15; + GRADIENT_INFRARED = 16; + GRADIENT_LAGOON = 17; + GRADIENT_FLUORESCENT = 18; + GRADIENT_BASIL = 19; + GRADIENT_SUBLIME = 20; + GRADIENT_SEA = 21; + GRADIENT_TANGERINE = 22; + } + oneof wallpaper { + WallpaperPreset wallpaperPreset = 1; + // This `FilePointer` is expected not to contain a `fileName`, `width`, + // `height`, or `caption`. + FilePointer wallpaperPhoto = 2; + } + oneof bubbleColor { + // Bubble setting is automatically determined based on the wallpaper setting, + // or `SOLID_ULTRAMARINE` for `noWallpaper` + AutomaticBubbleColor autoBubbleColor = 3; + BubbleColorPreset bubbleColorPreset = 4; - // If unset, use the default chat color - oneof color { - fixed32 solid = 2; // 0xAARRGGBB - Gradient gradient = 3; - } - } + // See AccountSettings.customChatColors + uint64 customColorId = 5; + } - message AutomaticBubbleColor { - } + // If unset, importers should consider there to be no wallpaper. - enum WallpaperPreset { - UNKNOWN_WALLPAPER_PRESET = 0; // Interpret as the wallpaper being unset - SOLID_BLUSH = 1; - SOLID_COPPER = 2; - SOLID_DUST = 3; - SOLID_CELADON = 4; - SOLID_RAINFOREST = 5; - SOLID_PACIFIC = 6; - SOLID_FROST = 7; - SOLID_NAVY = 8; - SOLID_LILAC = 9; - SOLID_PINK = 10; - SOLID_EGGPLANT = 11; - SOLID_SILVER = 12; - GRADIENT_SUNSET = 13; - GRADIENT_NOIR = 14; - GRADIENT_HEATMAP = 15; - GRADIENT_AQUA = 16; - GRADIENT_IRIDESCENT = 17; - GRADIENT_MONSTERA = 18; - GRADIENT_BLISS = 19; - GRADIENT_SKY = 20; - GRADIENT_PEACH = 21; - } + // If unset, importers should consider it to be AutomaticBubbleColor - enum BubbleColorPreset { - UNKNOWN_BUBBLE_COLOR_PRESET = 0; // Interpret as the user's default chat bubble color - SOLID_ULTRAMARINE = 1; - SOLID_CRIMSON = 2; - SOLID_VERMILION = 3; - SOLID_BURLAP = 4; - SOLID_FOREST = 5; - SOLID_WINTERGREEN = 6; - SOLID_TEAL = 7; - SOLID_BLUE = 8; - SOLID_INDIGO = 9; - SOLID_VIOLET = 10; - SOLID_PLUM = 11; - SOLID_TAUPE = 12; - SOLID_STEEL = 13; - GRADIENT_EMBER = 14; - GRADIENT_MIDNIGHT = 15; - GRADIENT_INFRARED = 16; - GRADIENT_LAGOON = 17; - GRADIENT_FLUORESCENT = 18; - GRADIENT_BASIL = 19; - GRADIENT_SUBLIME = 20; - GRADIENT_SEA = 21; - GRADIENT_TANGERINE = 22; - } - - // If unset, importers should consider there to be no wallpaper. - oneof wallpaper { - WallpaperPreset wallpaperPreset = 1; - // This `FilePointer` is expected not to contain a `fileName`, `width`, - // `height`, or `caption`. - FilePointer wallpaperPhoto = 2; - } - - // If unset, importers should consider it to be AutomaticBubbleColor - oneof bubbleColor { - // Bubble setting is automatically determined based on the wallpaper setting, - // or `SOLID_ULTRAMARINE` for `noWallpaper` - AutomaticBubbleColor autoBubbleColor = 3; - BubbleColorPreset bubbleColorPreset = 4; - - // See AccountSettings.customChatColors - uint64 customColorId = 5; - } - - bool dimWallpaperInDarkMode = 7; + bool dimWallpaperInDarkMode = 7; } - message NotificationProfile { - enum DayOfWeek { - UNKNOWN = 0; // Interpret as "Monday" - MONDAY = 1; - TUESDAY = 2; - WEDNESDAY = 3; - THURSDAY = 4; - FRIDAY = 5; - SATURDAY = 6; - SUNDAY = 7; - } + enum DayOfWeek { + UNKNOWN = 0; // Interpret as "Monday" + MONDAY = 1; + TUESDAY = 2; + WEDNESDAY = 3; + THURSDAY = 4; + FRIDAY = 5; + SATURDAY = 6; + SUNDAY = 7; + } - string name = 1; - optional string emoji = 2; - fixed32 color = 3; // 0xAARRGGBB - uint64 createdAtMs = 4; - bool allowAllCalls = 5; - bool allowAllMentions = 6; - repeated uint64 allowedMembers = 7; // generated recipient id for allowed groups and contacts - bool scheduleEnabled = 8; - uint32 scheduleStartTime = 9; // 24-hour clock int, 0000-2359 (e.g., 15, 900, 1130, 2345) - uint32 scheduleEndTime = 10; // 24-hour clock int, 0000-2359 (e.g., 15, 900, 1130, 2345) - repeated DayOfWeek scheduleDaysEnabled = 11; + string name = 1; + optional string emoji = 2; + fixed32 color = 3; // 0xAARRGGBB + uint64 createdAtMs = 4; + bool allowAllCalls = 5; + bool allowAllMentions = 6; + repeated uint64 allowedMembers = 7; // generated recipient id for allowed groups and contacts + bool scheduleEnabled = 8; + uint32 scheduleStartTime = 9; // 24-hour clock int, 0000-2359 (e.g., 15, 900, 1130, 2345) + uint32 scheduleEndTime = 10; // 24-hour clock int, 0000-2359 (e.g., 15, 900, 1130, 2345) + repeated DayOfWeek scheduleDaysEnabled = 11; } - message ChatFolder { - // Represents the default "All chats" folder record vs all other custom folders - enum FolderType { - UNKNOWN = 0; // Interpret as "Custom" - ALL = 1; - CUSTOM = 2; - } + enum FolderType { + UNKNOWN = 0; // Interpret as "Custom" + ALL = 1; + CUSTOM = 2; + } - string name = 1; - bool showOnlyUnread = 2; - bool showMutedChats = 3; - // Folder includes all 1:1 chats, unless excluded - bool includeAllIndividualChats = 4; - // Folder includes all group chats, unless excluded - bool includeAllGroupChats = 5; - FolderType folderType = 6; - repeated uint64 includedRecipientIds = 7; // generated recipient id of groups, contacts, and/or note to self - repeated uint64 excludedRecipientIds = 8; // generated recipient id of groups, contacts, and/or note to self + // Represents the default "All chats" folder record vs all other custom folders + + string name = 1; + bool showOnlyUnread = 2; + bool showMutedChats = 3; + // Folder includes all 1:1 chats, unless excluded + bool includeAllIndividualChats = 4; + // Folder includes all group chats, unless excluded + bool includeAllGroupChats = 5; + FolderType folderType = 6; + repeated uint64 includedRecipientIds = 7; // generated recipient id of groups, contacts, and/or note to self + repeated uint64 excludedRecipientIds = 8; // generated recipient id of groups, contacts, and/or note to self } +// footer was empty