2020-12-01 09:43:46 +00:00
|
|
|
package protocol
|
|
|
|
|
|
|
|
import (
|
2021-01-11 10:32:51 +00:00
|
|
|
"encoding/json"
|
|
|
|
|
2024-02-16 09:45:10 +00:00
|
|
|
"golang.org/x/exp/maps"
|
|
|
|
|
2023-04-26 15:37:18 +00:00
|
|
|
ensservice "github.com/status-im/status-go/services/ens"
|
|
|
|
|
2022-01-17 03:42:11 +00:00
|
|
|
"github.com/status-im/status-go/services/browsers"
|
2022-09-14 10:46:11 +00:00
|
|
|
"github.com/status-im/status-go/services/wallet"
|
2022-01-17 03:42:11 +00:00
|
|
|
|
2021-09-01 12:02:18 +00:00
|
|
|
"github.com/status-im/status-go/appmetrics"
|
2022-03-24 09:35:56 +00:00
|
|
|
"github.com/status-im/status-go/images"
|
2022-05-18 10:42:51 +00:00
|
|
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
2022-03-23 18:47:00 +00:00
|
|
|
"github.com/status-im/status-go/multiaccounts/settings"
|
2023-12-04 10:18:05 +00:00
|
|
|
walletsettings "github.com/status-im/status-go/multiaccounts/settings_wallet"
|
2020-12-01 09:43:46 +00:00
|
|
|
"github.com/status-im/status-go/protocol/common"
|
2020-11-18 09:16:51 +00:00
|
|
|
"github.com/status-im/status-go/protocol/communities"
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
"github.com/status-im/status-go/protocol/discord"
|
2020-12-01 09:43:46 +00:00
|
|
|
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
2022-09-29 11:50:23 +00:00
|
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
2024-02-20 15:49:39 +00:00
|
|
|
"github.com/status-im/status-go/protocol/storenodes"
|
2022-07-05 19:49:44 +00:00
|
|
|
"github.com/status-im/status-go/protocol/verification"
|
2021-03-31 16:23:45 +00:00
|
|
|
localnotifications "github.com/status-im/status-go/services/local-notifications"
|
2021-01-14 22:15:13 +00:00
|
|
|
"github.com/status-im/status-go/services/mailservers"
|
2020-12-01 09:43:46 +00:00
|
|
|
)
|
|
|
|
|
2021-08-20 14:26:13 +00:00
|
|
|
type RemovedMessage struct {
|
|
|
|
ChatID string `json:"chatId"`
|
|
|
|
MessageID string `json:"messageId"`
|
2023-02-01 00:57:35 +00:00
|
|
|
DeletedBy string `json:"deletedBy,omitempty"`
|
2021-08-20 14:26:13 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 10:00:59 +00:00
|
|
|
type ClearedHistory struct {
|
|
|
|
ChatID string `json:"chatId"`
|
|
|
|
ClearedAt uint64 `json:"clearedAt"`
|
|
|
|
}
|
|
|
|
|
2023-12-25 06:25:22 +00:00
|
|
|
type SeenUnseenMessages struct {
|
|
|
|
ChatID string `json:"chatId"`
|
|
|
|
Count uint64 `json:"count"`
|
|
|
|
CountWithMentions uint64 `json:"countWithMentions"`
|
|
|
|
Seen bool `json:"seen"`
|
|
|
|
}
|
|
|
|
|
2020-12-01 09:43:46 +00:00
|
|
|
type MessengerResponse struct {
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
Contacts []*Contact
|
|
|
|
Invitations []*GroupChatInvitation
|
|
|
|
CommunityChanges []*communities.CommunityChanges
|
|
|
|
AnonymousMetrics []*appmetrics.AppMetric
|
|
|
|
Mailservers []mailservers.Mailserver
|
2024-02-20 15:49:39 +00:00
|
|
|
CommunityStorenodes []storenodes.Storenode
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
Bookmarks []*browsers.Bookmark
|
|
|
|
Settings []*settings.SyncSettingField
|
2022-06-27 13:48:00 +00:00
|
|
|
IdentityImages []images.IdentityImage
|
2023-07-18 13:35:06 +00:00
|
|
|
CustomizationColor string
|
2023-06-28 19:45:36 +00:00
|
|
|
WatchOnlyAccounts []*accounts.Account
|
2023-05-16 10:48:00 +00:00
|
|
|
Keypairs []*accounts.Keypair
|
2023-07-16 11:11:48 +00:00
|
|
|
AccountsPositions []*accounts.Account
|
2023-12-04 10:18:05 +00:00
|
|
|
TokenPreferences []walletsettings.TokenPreferences
|
2024-01-17 13:12:49 +00:00
|
|
|
CollectiblePreferences []walletsettings.CollectiblePreferences
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
DiscordCategories []*discord.Category
|
|
|
|
DiscordChannels []*discord.Channel
|
|
|
|
DiscordOldestMessageTimestamp int
|
2023-02-27 10:19:18 +00:00
|
|
|
BackupHandled bool
|
2021-01-11 10:32:51 +00:00
|
|
|
|
2021-03-31 16:23:45 +00:00
|
|
|
// notifications a list of notifications derived from messenger events
|
|
|
|
// that are useful to notify the user about
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
installations map[string]*multidevice.Installation
|
2024-03-29 10:22:44 +00:00
|
|
|
notifications map[string]*localnotifications.Notification
|
|
|
|
requestsToJoinCommunity map[string]*communities.RequestToJoin
|
|
|
|
chats map[string]*Chat
|
|
|
|
removedChats map[string]bool
|
|
|
|
removedMessages map[string]*RemovedMessage
|
|
|
|
deletedMessages map[string]string
|
|
|
|
communities map[string]*communities.Community
|
|
|
|
communitiesSettings map[string]*communities.CommunitySettings
|
|
|
|
activityCenterNotifications map[string]*ActivityCenterNotification
|
|
|
|
activityCenterState *ActivityCenterState
|
|
|
|
messages map[string]*common.Message
|
|
|
|
pinMessages map[string]*common.PinMessage
|
|
|
|
discordMessages map[string]*protobuf.DiscordMessage
|
|
|
|
discordMessageAttachments map[string]*protobuf.DiscordMessageAttachment
|
|
|
|
discordMessageAuthors map[string]*protobuf.DiscordMessageAuthor
|
|
|
|
currentStatus *UserStatus
|
|
|
|
statusUpdates map[string]UserStatus
|
|
|
|
clearedHistories map[string]*ClearedHistory
|
|
|
|
verificationRequests map[string]*verification.Request
|
|
|
|
trustStatus map[string]verification.TrustStatus
|
|
|
|
emojiReactions map[string]*EmojiReaction
|
|
|
|
savedAddresses map[string]*wallet.SavedAddress
|
|
|
|
ensUsernameDetails []*ensservice.UsernameDetail
|
|
|
|
updatedProfileShowcaseContactIDs map[string]bool
|
|
|
|
seenAndUnseenMessages map[string]*SeenUnseenMessages
|
2021-01-11 10:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) MarshalJSON() ([]byte, error) {
|
|
|
|
responseItem := struct {
|
2022-07-05 19:49:44 +00:00
|
|
|
Chats []*Chat `json:"chats,omitempty"`
|
|
|
|
RemovedChats []string `json:"removedChats,omitempty"`
|
|
|
|
RemovedMessages []*RemovedMessage `json:"removedMessages,omitempty"`
|
2024-02-22 10:25:13 +00:00
|
|
|
DeletedMessages map[string][]string `json:"deletedMessages,omitempty"`
|
2022-07-05 19:49:44 +00:00
|
|
|
Messages []*common.Message `json:"messages,omitempty"`
|
|
|
|
Contacts []*Contact `json:"contacts,omitempty"`
|
|
|
|
Installations []*multidevice.Installation `json:"installations,omitempty"`
|
|
|
|
PinMessages []*common.PinMessage `json:"pinMessages,omitempty"`
|
|
|
|
EmojiReactions []*EmojiReaction `json:"emojiReactions,omitempty"`
|
|
|
|
Invitations []*GroupChatInvitation `json:"invitations,omitempty"`
|
|
|
|
CommunityChanges []*communities.CommunityChanges `json:"communityChanges,omitempty"`
|
|
|
|
RequestsToJoinCommunity []*communities.RequestToJoin `json:"requestsToJoinCommunity,omitempty"`
|
|
|
|
Mailservers []mailservers.Mailserver `json:"mailservers,omitempty"`
|
2024-02-20 15:49:39 +00:00
|
|
|
CommunityStorenodes []storenodes.Storenode `json:"communityStorenodes,omitempty"`
|
2022-07-05 19:49:44 +00:00
|
|
|
Bookmarks []*browsers.Bookmark `json:"bookmarks,omitempty"`
|
|
|
|
ClearedHistories []*ClearedHistory `json:"clearedHistories,omitempty"`
|
|
|
|
VerificationRequests []*verification.Request `json:"verificationRequests,omitempty"`
|
|
|
|
TrustStatus map[string]verification.TrustStatus `json:"trustStatus,omitempty"`
|
2021-03-31 16:23:45 +00:00
|
|
|
// Notifications a list of notifications derived from messenger events
|
|
|
|
// that are useful to notify the user about
|
2024-03-29 10:22:44 +00:00
|
|
|
Notifications []*localnotifications.Notification `json:"notifications"`
|
|
|
|
Communities []*communities.Community `json:"communities,omitempty"`
|
|
|
|
CommunitiesSettings []*communities.CommunitySettings `json:"communitiesSettings,omitempty"`
|
|
|
|
ActivityCenterNotifications []*ActivityCenterNotification `json:"activityCenterNotifications,omitempty"`
|
|
|
|
ActivityCenterState *ActivityCenterState `json:"activityCenterState,omitempty"`
|
|
|
|
CurrentStatus *UserStatus `json:"currentStatus,omitempty"`
|
|
|
|
StatusUpdates []UserStatus `json:"statusUpdates,omitempty"`
|
|
|
|
Settings []*settings.SyncSettingField `json:"settings,omitempty"`
|
|
|
|
IdentityImages []images.IdentityImage `json:"identityImages,omitempty"`
|
|
|
|
CustomizationColor string `json:"customizationColor,omitempty"`
|
|
|
|
WatchOnlyAccounts []*accounts.Account `json:"watchOnlyAccounts,omitempty"`
|
|
|
|
Keypairs []*accounts.Keypair `json:"keypairs,omitempty"`
|
|
|
|
AccountsPositions []*accounts.Account `json:"accountsPositions,omitempty"`
|
|
|
|
TokenPreferences []walletsettings.TokenPreferences `json:"tokenPreferences,omitempty"`
|
|
|
|
CollectiblePreferences []walletsettings.CollectiblePreferences `json:"collectiblePreferences,omitempty"`
|
|
|
|
DiscordCategories []*discord.Category `json:"discordCategories,omitempty"`
|
|
|
|
DiscordChannels []*discord.Channel `json:"discordChannels,omitempty"`
|
|
|
|
DiscordOldestMessageTimestamp int `json:"discordOldestMessageTimestamp"`
|
|
|
|
DiscordMessages []*protobuf.DiscordMessage `json:"discordMessages,omitempty"`
|
|
|
|
DiscordMessageAttachments []*protobuf.DiscordMessageAttachment `json:"discordMessageAtachments,omitempty"`
|
|
|
|
SavedAddresses []*wallet.SavedAddress `json:"savedAddresses,omitempty"`
|
|
|
|
EnsUsernameDetails []*ensservice.UsernameDetail `json:"ensUsernameDetails,omitempty"`
|
|
|
|
UpdatedProfileShowcaseContactIDs []string `json:"updatedProfileShowcaseContactIDs,omitempty"`
|
|
|
|
SeenAndUnseenMessages []*SeenUnseenMessages `json:"seenAndUnseenMessages,omitempty"`
|
2021-01-11 10:32:51 +00:00
|
|
|
}{
|
2022-07-05 19:49:44 +00:00
|
|
|
Contacts: r.Contacts,
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
Installations: r.Installations(),
|
2022-07-05 19:49:44 +00:00
|
|
|
Invitations: r.Invitations,
|
|
|
|
CommunityChanges: r.CommunityChanges,
|
2024-02-08 09:24:12 +00:00
|
|
|
RequestsToJoinCommunity: r.RequestsToJoinCommunity(),
|
2022-07-05 19:49:44 +00:00
|
|
|
Mailservers: r.Mailservers,
|
2024-02-20 15:49:39 +00:00
|
|
|
CommunityStorenodes: r.CommunityStorenodes,
|
2022-07-05 19:49:44 +00:00
|
|
|
Bookmarks: r.Bookmarks,
|
|
|
|
CurrentStatus: r.currentStatus,
|
|
|
|
Settings: r.Settings,
|
|
|
|
IdentityImages: r.IdentityImages,
|
2023-07-18 13:35:06 +00:00
|
|
|
CustomizationColor: r.CustomizationColor,
|
2023-06-28 19:45:36 +00:00
|
|
|
WatchOnlyAccounts: r.WatchOnlyAccounts,
|
2023-05-16 10:48:00 +00:00
|
|
|
Keypairs: r.Keypairs,
|
2023-07-16 11:11:48 +00:00
|
|
|
AccountsPositions: r.AccountsPositions,
|
2023-12-04 10:18:05 +00:00
|
|
|
TokenPreferences: r.TokenPreferences,
|
2024-01-17 13:12:49 +00:00
|
|
|
CollectiblePreferences: r.CollectiblePreferences,
|
2022-07-05 19:49:44 +00:00
|
|
|
|
2024-03-29 10:22:44 +00:00
|
|
|
Messages: r.Messages(),
|
|
|
|
VerificationRequests: r.VerificationRequests(),
|
|
|
|
SavedAddresses: r.SavedAddresses(),
|
|
|
|
Notifications: r.Notifications(),
|
|
|
|
Chats: r.Chats(),
|
|
|
|
Communities: r.Communities(),
|
|
|
|
CommunitiesSettings: r.CommunitiesSettings(),
|
|
|
|
RemovedChats: r.RemovedChats(),
|
|
|
|
RemovedMessages: r.RemovedMessages(),
|
|
|
|
DeletedMessages: r.DeletedMessagesInChats(),
|
|
|
|
ClearedHistories: r.ClearedHistories(),
|
|
|
|
ActivityCenterNotifications: r.ActivityCenterNotifications(),
|
|
|
|
ActivityCenterState: r.ActivityCenterState(),
|
|
|
|
PinMessages: r.PinMessages(),
|
|
|
|
EmojiReactions: r.EmojiReactions(),
|
|
|
|
StatusUpdates: r.StatusUpdates(),
|
|
|
|
DiscordCategories: r.DiscordCategories,
|
|
|
|
DiscordChannels: r.DiscordChannels,
|
|
|
|
DiscordOldestMessageTimestamp: r.DiscordOldestMessageTimestamp,
|
|
|
|
EnsUsernameDetails: r.EnsUsernameDetails(),
|
|
|
|
UpdatedProfileShowcaseContactIDs: r.GetUpdatedProfileShowcaseContactIDs(),
|
|
|
|
SeenAndUnseenMessages: r.GetSeenAndUnseenMessages(),
|
2021-01-11 10:32:51 +00:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:49:44 +00:00
|
|
|
responseItem.TrustStatus = r.TrustStatus()
|
2021-01-11 10:32:51 +00:00
|
|
|
return json.Marshal(responseItem)
|
2020-12-01 09:43:46 +00:00
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) Chats() []*Chat {
|
|
|
|
var chats []*Chat
|
|
|
|
for _, chat := range r.chats {
|
|
|
|
chats = append(chats, chat)
|
|
|
|
}
|
|
|
|
return chats
|
|
|
|
}
|
|
|
|
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
func (r *MessengerResponse) Installations() []*multidevice.Installation {
|
|
|
|
var is []*multidevice.Installation
|
|
|
|
for _, i := range r.installations {
|
|
|
|
is = append(is, i)
|
|
|
|
}
|
|
|
|
return is
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) RemovedChats() []string {
|
|
|
|
var chats []string
|
|
|
|
for chatID := range r.removedChats {
|
|
|
|
chats = append(chats, chatID)
|
|
|
|
}
|
|
|
|
return chats
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:26:13 +00:00
|
|
|
func (r *MessengerResponse) RemovedMessages() []*RemovedMessage {
|
|
|
|
var messages []*RemovedMessage
|
2021-07-26 21:06:32 +00:00
|
|
|
for messageID := range r.removedMessages {
|
2021-08-20 14:26:13 +00:00
|
|
|
messages = append(messages, r.removedMessages[messageID])
|
2021-07-26 21:06:32 +00:00
|
|
|
}
|
|
|
|
return messages
|
|
|
|
}
|
|
|
|
|
2024-02-22 10:25:13 +00:00
|
|
|
func (r *MessengerResponse) DeletedMessages() map[string]string {
|
|
|
|
return r.deletedMessages
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) DeletedMessagesInChats() map[string][]string {
|
|
|
|
deletedMessagesInChats := make(map[string][]string)
|
|
|
|
for messageID, chatID := range r.deletedMessages {
|
|
|
|
deletedMessagesInChats[chatID] = append(deletedMessagesInChats[chatID], messageID)
|
|
|
|
}
|
|
|
|
return deletedMessagesInChats
|
|
|
|
}
|
|
|
|
|
2022-02-10 10:00:59 +00:00
|
|
|
func (r *MessengerResponse) ClearedHistories() []*ClearedHistory {
|
|
|
|
var clearedHistories []*ClearedHistory
|
|
|
|
for chatID := range r.clearedHistories {
|
|
|
|
clearedHistories = append(clearedHistories, r.clearedHistories[chatID])
|
|
|
|
}
|
|
|
|
return clearedHistories
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) Communities() []*communities.Community {
|
|
|
|
var communities []*communities.Community
|
|
|
|
for _, c := range r.communities {
|
|
|
|
communities = append(communities, c)
|
|
|
|
}
|
|
|
|
return communities
|
|
|
|
}
|
|
|
|
|
2022-03-08 15:25:00 +00:00
|
|
|
func (r *MessengerResponse) CommunitiesSettings() []*communities.CommunitySettings {
|
|
|
|
var settings []*communities.CommunitySettings
|
|
|
|
for _, s := range r.communitiesSettings {
|
|
|
|
settings = append(settings, s)
|
|
|
|
}
|
|
|
|
return settings
|
|
|
|
}
|
|
|
|
|
2021-03-31 16:23:45 +00:00
|
|
|
func (r *MessengerResponse) Notifications() []*localnotifications.Notification {
|
|
|
|
var notifications []*localnotifications.Notification
|
|
|
|
for _, n := range r.notifications {
|
|
|
|
notifications = append(notifications, n)
|
|
|
|
}
|
|
|
|
return notifications
|
|
|
|
}
|
|
|
|
|
2023-02-13 20:09:20 +00:00
|
|
|
func (r *MessengerResponse) VerificationRequests() []*verification.Request {
|
|
|
|
var verifications []*verification.Request
|
|
|
|
for _, v := range r.verificationRequests {
|
|
|
|
verifications = append(verifications, v)
|
|
|
|
}
|
|
|
|
return verifications
|
|
|
|
}
|
|
|
|
|
2021-05-14 21:22:50 +00:00
|
|
|
func (r *MessengerResponse) PinMessages() []*common.PinMessage {
|
|
|
|
var pinMessages []*common.PinMessage
|
|
|
|
for _, pm := range r.pinMessages {
|
|
|
|
pinMessages = append(pinMessages, pm)
|
|
|
|
}
|
|
|
|
return pinMessages
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:49:44 +00:00
|
|
|
func (r *MessengerResponse) TrustStatus() map[string]verification.TrustStatus {
|
|
|
|
if len(r.trustStatus) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
result := make(map[string]verification.TrustStatus)
|
|
|
|
for contactID, trustStatus := range r.trustStatus {
|
|
|
|
result[contactID] = trustStatus
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-07-22 17:41:49 +00:00
|
|
|
func (r *MessengerResponse) StatusUpdates() []UserStatus {
|
|
|
|
var userStatus []UserStatus
|
|
|
|
for pk, s := range r.statusUpdates {
|
|
|
|
s.PublicKey = pk
|
|
|
|
userStatus = append(userStatus, s)
|
|
|
|
}
|
|
|
|
return userStatus
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) IsEmpty() bool {
|
|
|
|
return len(r.chats)+
|
2021-06-03 13:11:55 +00:00
|
|
|
len(r.messages)+
|
2021-05-14 21:22:50 +00:00
|
|
|
len(r.pinMessages)+
|
2021-01-11 10:32:51 +00:00
|
|
|
len(r.Contacts)+
|
2022-01-17 03:42:11 +00:00
|
|
|
len(r.Bookmarks)+
|
2022-02-10 10:00:59 +00:00
|
|
|
len(r.clearedHistories)+
|
2022-03-23 18:47:00 +00:00
|
|
|
len(r.Settings)+
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
len(r.installations)+
|
2021-01-11 10:32:51 +00:00
|
|
|
len(r.Invitations)+
|
2023-02-13 20:09:20 +00:00
|
|
|
len(r.emojiReactions)+
|
2021-01-11 10:32:51 +00:00
|
|
|
len(r.communities)+
|
|
|
|
len(r.CommunityChanges)+
|
|
|
|
len(r.removedChats)+
|
2021-07-26 21:06:32 +00:00
|
|
|
len(r.removedMessages)+
|
2024-02-22 10:25:13 +00:00
|
|
|
len(r.deletedMessages)+
|
2021-01-11 10:32:51 +00:00
|
|
|
len(r.Mailservers)+
|
2024-02-20 15:49:39 +00:00
|
|
|
len(r.CommunityStorenodes)+
|
2022-03-24 09:35:56 +00:00
|
|
|
len(r.IdentityImages)+
|
2023-06-28 19:45:36 +00:00
|
|
|
len(r.WatchOnlyAccounts)+
|
2023-05-16 10:48:00 +00:00
|
|
|
len(r.Keypairs)+
|
2023-07-16 11:11:48 +00:00
|
|
|
len(r.AccountsPositions)+
|
2023-12-04 10:18:05 +00:00
|
|
|
len(r.TokenPreferences)+
|
2024-01-17 13:12:49 +00:00
|
|
|
len(r.CollectiblePreferences)+
|
2021-03-31 16:23:45 +00:00
|
|
|
len(r.notifications)+
|
2021-07-22 17:41:49 +00:00
|
|
|
len(r.statusUpdates)+
|
2021-04-07 12:57:14 +00:00
|
|
|
len(r.activityCenterNotifications)+
|
2022-07-05 19:49:44 +00:00
|
|
|
len(r.trustStatus)+
|
2023-02-13 20:09:20 +00:00
|
|
|
len(r.verificationRequests)+
|
2024-02-08 09:24:12 +00:00
|
|
|
len(r.requestsToJoinCommunity)+
|
2023-04-17 14:44:48 +00:00
|
|
|
len(r.savedAddresses)+
|
2024-03-29 10:22:44 +00:00
|
|
|
len(r.updatedProfileShowcaseContactIDs)+
|
2023-12-25 06:25:22 +00:00
|
|
|
len(r.seenAndUnseenMessages)+
|
2023-04-26 15:37:18 +00:00
|
|
|
len(r.ensUsernameDetails) == 0 &&
|
2023-02-17 10:08:08 +00:00
|
|
|
r.currentStatus == nil &&
|
2023-06-05 11:10:26 +00:00
|
|
|
r.activityCenterState == nil &&
|
2024-02-07 15:20:54 +00:00
|
|
|
r.CustomizationColor == ""
|
2020-12-01 09:43:46 +00:00
|
|
|
}
|
|
|
|
|
2020-12-03 17:04:38 +00:00
|
|
|
// Merge takes another response and appends the new Chats & new Messages and replaces
|
|
|
|
// the existing Messages & Chats if they have the same ID
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) Merge(response *MessengerResponse) error {
|
2023-02-13 20:09:20 +00:00
|
|
|
if len(response.Invitations)+
|
2021-01-11 10:32:51 +00:00
|
|
|
len(response.Mailservers)+
|
2022-02-10 10:00:59 +00:00
|
|
|
len(response.clearedHistories)+
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
len(response.DiscordChannels)+
|
2022-09-15 14:13:35 +00:00
|
|
|
len(response.DiscordCategories) != 0 {
|
2020-12-01 09:43:46 +00:00
|
|
|
return ErrNotImplemented
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
r.AddChats(response.Chats())
|
|
|
|
r.AddRemovedChats(response.RemovedChats())
|
2021-07-26 21:06:32 +00:00
|
|
|
r.AddRemovedMessages(response.RemovedMessages())
|
2024-02-22 10:25:13 +00:00
|
|
|
r.MergeDeletedMessages(response.DeletedMessages())
|
2021-03-31 16:23:45 +00:00
|
|
|
r.AddNotifications(response.Notifications())
|
2021-06-03 13:11:55 +00:00
|
|
|
r.AddMessages(response.Messages())
|
2023-02-13 20:09:20 +00:00
|
|
|
r.AddContacts(response.Contacts)
|
2021-01-11 10:32:51 +00:00
|
|
|
r.AddCommunities(response.Communities())
|
2023-12-07 16:02:37 +00:00
|
|
|
r.UpdateCommunitySettings(response.CommunitiesSettings())
|
2021-05-14 21:22:50 +00:00
|
|
|
r.AddPinMessages(response.PinMessages())
|
2023-02-13 20:09:20 +00:00
|
|
|
r.AddVerificationRequests(response.VerificationRequests())
|
2022-07-05 19:49:44 +00:00
|
|
|
r.AddTrustStatuses(response.trustStatus)
|
2021-12-02 14:23:02 +00:00
|
|
|
r.AddActivityCenterNotifications(response.ActivityCenterNotifications())
|
2023-04-26 14:00:54 +00:00
|
|
|
r.SetActivityCenterState(response.ActivityCenterState())
|
2023-02-13 20:09:20 +00:00
|
|
|
r.AddEmojiReactions(response.EmojiReactions())
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
r.AddInstallations(response.Installations())
|
2023-02-13 20:09:20 +00:00
|
|
|
r.AddSavedAddresses(response.SavedAddresses())
|
2023-04-26 15:37:18 +00:00
|
|
|
r.AddEnsUsernameDetails(response.EnsUsernameDetails())
|
2024-02-08 09:24:12 +00:00
|
|
|
r.AddRequestsToJoinCommunity(response.RequestsToJoinCommunity())
|
2023-04-26 15:37:18 +00:00
|
|
|
r.AddBookmarks(response.GetBookmarks())
|
2024-03-29 10:22:44 +00:00
|
|
|
r.AddSeveralUpdatedProfileShowcaseContactIDs(response.GetUpdatedProfileShowcaseContactIDs())
|
2023-12-25 06:25:22 +00:00
|
|
|
r.AddSeveralSeenAndUnseenMessages(response.GetSeenAndUnseenMessages())
|
2022-09-15 14:13:35 +00:00
|
|
|
r.CommunityChanges = append(r.CommunityChanges, response.CommunityChanges...)
|
2023-02-27 10:19:18 +00:00
|
|
|
r.BackupHandled = response.BackupHandled
|
2023-07-18 13:35:06 +00:00
|
|
|
r.CustomizationColor = response.CustomizationColor
|
2023-06-28 19:45:36 +00:00
|
|
|
r.WatchOnlyAccounts = append(r.WatchOnlyAccounts, response.WatchOnlyAccounts...)
|
2023-05-16 10:48:00 +00:00
|
|
|
r.Keypairs = append(r.Keypairs, response.Keypairs...)
|
2023-12-04 10:18:05 +00:00
|
|
|
r.AccountsPositions = append(r.AccountsPositions, response.AccountsPositions...)
|
|
|
|
r.TokenPreferences = append(r.TokenPreferences, response.TokenPreferences...)
|
2024-01-17 13:12:49 +00:00
|
|
|
r.CollectiblePreferences = append(r.CollectiblePreferences, response.CollectiblePreferences...)
|
2020-12-03 17:04:38 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) AddCommunities(communities []*communities.Community) {
|
|
|
|
for _, overrideCommunity := range communities {
|
|
|
|
r.AddCommunity(overrideCommunity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddCommunity(c *communities.Community) {
|
|
|
|
if r.communities == nil {
|
|
|
|
r.communities = make(map[string]*communities.Community)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.communities[c.IDString()] = c
|
|
|
|
}
|
|
|
|
|
2022-03-08 15:25:00 +00:00
|
|
|
func (r *MessengerResponse) AddCommunitySettings(c *communities.CommunitySettings) {
|
|
|
|
if r.communitiesSettings == nil {
|
|
|
|
r.communitiesSettings = make(map[string]*communities.CommunitySettings)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.communitiesSettings[c.CommunityID] = c
|
|
|
|
}
|
|
|
|
|
2023-12-07 16:02:37 +00:00
|
|
|
func (r *MessengerResponse) UpdateCommunitySettings(communitySettings []*communities.CommunitySettings) {
|
|
|
|
for _, communitySetting := range communitySettings {
|
|
|
|
r.AddCommunitySettings(communitySetting)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-14 14:15:46 +00:00
|
|
|
func (r *MessengerResponse) AddRequestsToJoinCommunity(requestsToJoin []*communities.RequestToJoin) {
|
2024-02-08 09:24:12 +00:00
|
|
|
for _, rq := range requestsToJoin {
|
|
|
|
r.AddRequestToJoinCommunity(rq)
|
|
|
|
}
|
2023-06-14 14:15:46 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 09:18:47 +00:00
|
|
|
func (r *MessengerResponse) AddRequestToJoinCommunity(requestToJoin *communities.RequestToJoin) {
|
2024-02-08 09:24:12 +00:00
|
|
|
if r.requestsToJoinCommunity == nil {
|
|
|
|
r.requestsToJoinCommunity = make(map[string]*communities.RequestToJoin)
|
|
|
|
}
|
|
|
|
r.requestsToJoinCommunity[requestToJoin.ID.String()] = requestToJoin
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) RequestsToJoinCommunity() []*communities.RequestToJoin {
|
|
|
|
var rs []*communities.RequestToJoin
|
|
|
|
for _, r := range r.requestsToJoinCommunity {
|
|
|
|
rs = append(rs, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rs
|
2023-04-21 09:18:47 +00:00
|
|
|
}
|
|
|
|
|
2022-12-29 06:16:19 +00:00
|
|
|
func (r *MessengerResponse) AddSetting(s *settings.SyncSettingField) {
|
|
|
|
r.Settings = append(r.Settings, s)
|
|
|
|
}
|
|
|
|
|
2022-01-17 03:42:11 +00:00
|
|
|
func (r *MessengerResponse) AddBookmark(bookmark *browsers.Bookmark) {
|
|
|
|
r.Bookmarks = append(r.Bookmarks, bookmark)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddBookmarks(bookmarks []*browsers.Bookmark) {
|
|
|
|
for _, b := range bookmarks {
|
|
|
|
r.AddBookmark(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-26 15:37:18 +00:00
|
|
|
func (r *MessengerResponse) GetBookmarks() []*browsers.Bookmark {
|
|
|
|
return r.Bookmarks
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:49:44 +00:00
|
|
|
func (r *MessengerResponse) AddVerificationRequest(vr *verification.Request) {
|
2023-02-13 20:09:20 +00:00
|
|
|
if r.verificationRequests == nil {
|
|
|
|
r.verificationRequests = make(map[string]*verification.Request)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.verificationRequests[vr.ID] = vr
|
2022-07-05 19:49:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddVerificationRequests(vrs []*verification.Request) {
|
|
|
|
for _, vr := range vrs {
|
|
|
|
r.AddVerificationRequest(vr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddTrustStatus(contactID string, trustStatus verification.TrustStatus) {
|
|
|
|
if r.trustStatus == nil {
|
|
|
|
r.trustStatus = make(map[string]verification.TrustStatus)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.trustStatus[contactID] = trustStatus
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddTrustStatuses(ts map[string]verification.TrustStatus) {
|
|
|
|
if r.trustStatus == nil {
|
|
|
|
r.trustStatus = make(map[string]verification.TrustStatus)
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range ts {
|
|
|
|
r.trustStatus[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) AddChat(c *Chat) {
|
|
|
|
if r.chats == nil {
|
|
|
|
r.chats = make(map[string]*Chat)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.chats[c.ID] = c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddChats(chats []*Chat) {
|
|
|
|
for _, c := range chats {
|
|
|
|
r.AddChat(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 20:09:20 +00:00
|
|
|
func (r *MessengerResponse) AddEmojiReactions(ers []*EmojiReaction) {
|
|
|
|
for _, e := range ers {
|
|
|
|
r.AddEmojiReaction(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddEmojiReaction(er *EmojiReaction) {
|
|
|
|
if r.emojiReactions == nil {
|
|
|
|
r.emojiReactions = make(map[string]*EmojiReaction)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.emojiReactions[er.ID()] = er
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) EmojiReactions() []*EmojiReaction {
|
|
|
|
var ers []*EmojiReaction
|
|
|
|
for _, er := range r.emojiReactions {
|
|
|
|
ers = append(ers, er)
|
|
|
|
}
|
|
|
|
return ers
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddSavedAddresses(ers []*wallet.SavedAddress) {
|
|
|
|
for _, e := range ers {
|
|
|
|
r.AddSavedAddress(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddSavedAddress(er *wallet.SavedAddress) {
|
|
|
|
if r.savedAddresses == nil {
|
|
|
|
r.savedAddresses = make(map[string]*wallet.SavedAddress)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.savedAddresses[er.ID()] = er
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) SavedAddresses() []*wallet.SavedAddress {
|
2024-02-16 09:45:10 +00:00
|
|
|
return maps.Values(r.savedAddresses)
|
2023-02-13 20:09:20 +00:00
|
|
|
}
|
|
|
|
|
2023-04-26 15:37:18 +00:00
|
|
|
func (r *MessengerResponse) AddEnsUsernameDetail(detail *ensservice.UsernameDetail) {
|
|
|
|
r.ensUsernameDetails = append(r.ensUsernameDetails, detail)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddEnsUsernameDetails(details []*ensservice.UsernameDetail) {
|
|
|
|
r.ensUsernameDetails = append(r.ensUsernameDetails, details...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) EnsUsernameDetails() []*ensservice.UsernameDetail {
|
|
|
|
return r.ensUsernameDetails
|
|
|
|
}
|
|
|
|
|
2021-03-31 16:23:45 +00:00
|
|
|
func (r *MessengerResponse) AddNotification(n *localnotifications.Notification) {
|
|
|
|
if r.notifications == nil {
|
|
|
|
r.notifications = make(map[string]*localnotifications.Notification)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.notifications[n.ID.String()] = n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) ClearNotifications() {
|
|
|
|
r.notifications = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddNotifications(notifications []*localnotifications.Notification) {
|
|
|
|
for _, c := range notifications {
|
|
|
|
r.AddNotification(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-11 10:32:51 +00:00
|
|
|
func (r *MessengerResponse) AddRemovedChats(chats []string) {
|
|
|
|
for _, c := range chats {
|
|
|
|
r.AddRemovedChat(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddRemovedChat(chatID string) {
|
|
|
|
if r.removedChats == nil {
|
|
|
|
r.removedChats = make(map[string]bool)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.removedChats[chatID] = true
|
|
|
|
}
|
2021-04-07 12:57:14 +00:00
|
|
|
|
2021-08-20 14:26:13 +00:00
|
|
|
func (r *MessengerResponse) AddRemovedMessages(messages []*RemovedMessage) {
|
2021-07-26 21:06:32 +00:00
|
|
|
for _, m := range messages {
|
|
|
|
r.AddRemovedMessage(m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:26:13 +00:00
|
|
|
func (r *MessengerResponse) AddRemovedMessage(rm *RemovedMessage) {
|
2021-07-26 21:06:32 +00:00
|
|
|
if r.removedMessages == nil {
|
2021-08-20 14:26:13 +00:00
|
|
|
r.removedMessages = make(map[string]*RemovedMessage)
|
2021-07-26 21:06:32 +00:00
|
|
|
}
|
|
|
|
|
2021-08-20 14:26:13 +00:00
|
|
|
r.removedMessages[rm.MessageID] = rm
|
2021-09-08 09:55:06 +00:00
|
|
|
// Remove original message from the map
|
|
|
|
|
|
|
|
if len(r.messages) != 0 && r.messages[rm.MessageID] != nil {
|
|
|
|
delete(r.messages, rm.MessageID)
|
|
|
|
}
|
2021-07-26 21:06:32 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 19:44:49 +00:00
|
|
|
func (r *MessengerResponse) AddDeletedMessages(messagesToAdd []*protobuf.DeleteCommunityMemberMessage) {
|
2024-02-22 10:25:13 +00:00
|
|
|
if r.deletedMessages == nil {
|
|
|
|
r.deletedMessages = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, message := range messagesToAdd {
|
2024-03-19 19:44:49 +00:00
|
|
|
r.deletedMessages[message.Id] = message.ChatId
|
2024-02-22 10:25:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) MergeDeletedMessages(messagesToAdd map[string]string) {
|
|
|
|
if r.deletedMessages == nil {
|
|
|
|
r.deletedMessages = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
for messageID, chatID := range messagesToAdd {
|
|
|
|
r.deletedMessages[messageID] = chatID
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-10 10:00:59 +00:00
|
|
|
func (r *MessengerResponse) AddClearedHistory(ch *ClearedHistory) {
|
|
|
|
if r.clearedHistories == nil {
|
|
|
|
r.clearedHistories = make(map[string]*ClearedHistory)
|
|
|
|
}
|
|
|
|
|
|
|
|
existingClearedHistory, ok := r.clearedHistories[ch.ChatID]
|
|
|
|
if !ok || existingClearedHistory.ClearedAt < ch.ClearedAt {
|
|
|
|
r.clearedHistories[ch.ChatID] = ch
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-07 12:57:14 +00:00
|
|
|
func (r *MessengerResponse) AddActivityCenterNotifications(ns []*ActivityCenterNotification) {
|
|
|
|
for _, n := range ns {
|
|
|
|
r.AddActivityCenterNotification(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddActivityCenterNotification(n *ActivityCenterNotification) {
|
|
|
|
if r.activityCenterNotifications == nil {
|
|
|
|
r.activityCenterNotifications = make(map[string]*ActivityCenterNotification)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.activityCenterNotifications[n.ID.String()] = n
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:57:51 +00:00
|
|
|
func (r *MessengerResponse) RemoveActivityCenterNotification(id string) bool {
|
|
|
|
if r.activityCenterNotifications == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := r.activityCenterNotifications[id]; ok {
|
|
|
|
delete(r.activityCenterNotifications, id)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-04-07 12:57:14 +00:00
|
|
|
func (r *MessengerResponse) ActivityCenterNotifications() []*ActivityCenterNotification {
|
|
|
|
var ns []*ActivityCenterNotification
|
|
|
|
for _, n := range r.activityCenterNotifications {
|
|
|
|
ns = append(ns, n)
|
|
|
|
}
|
|
|
|
return ns
|
|
|
|
}
|
2021-05-14 21:22:50 +00:00
|
|
|
|
2023-02-17 10:08:08 +00:00
|
|
|
func (r *MessengerResponse) SetActivityCenterState(activityCenterState *ActivityCenterState) {
|
|
|
|
r.activityCenterState = activityCenterState
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) ActivityCenterState() *ActivityCenterState {
|
|
|
|
return r.activityCenterState
|
|
|
|
}
|
|
|
|
|
2021-05-14 21:22:50 +00:00
|
|
|
func (r *MessengerResponse) AddPinMessage(pm *common.PinMessage) {
|
|
|
|
if r.pinMessages == nil {
|
|
|
|
r.pinMessages = make(map[string]*common.PinMessage)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.pinMessages[pm.ID] = pm
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddPinMessages(pms []*common.PinMessage) {
|
|
|
|
for _, pm := range pms {
|
|
|
|
r.AddPinMessage(pm)
|
|
|
|
}
|
|
|
|
}
|
2021-03-25 15:15:22 +00:00
|
|
|
|
2021-07-22 17:41:49 +00:00
|
|
|
func (r *MessengerResponse) SetCurrentStatus(status UserStatus) {
|
|
|
|
r.currentStatus = &status
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddStatusUpdate(upd UserStatus) {
|
|
|
|
if r.statusUpdates == nil {
|
|
|
|
r.statusUpdates = make(map[string]UserStatus)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.statusUpdates[upd.PublicKey] = upd
|
|
|
|
}
|
|
|
|
|
2022-09-29 11:50:23 +00:00
|
|
|
func (r *MessengerResponse) DiscordMessages() []*protobuf.DiscordMessage {
|
|
|
|
var ms []*protobuf.DiscordMessage
|
|
|
|
for _, m := range r.discordMessages {
|
|
|
|
ms = append(ms, m)
|
|
|
|
}
|
|
|
|
return ms
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) DiscordMessageAuthors() []*protobuf.DiscordMessageAuthor {
|
|
|
|
var authors []*protobuf.DiscordMessageAuthor
|
|
|
|
for _, author := range r.discordMessageAuthors {
|
|
|
|
authors = append(authors, author)
|
|
|
|
}
|
|
|
|
return authors
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) DiscordMessageAttachments() []*protobuf.DiscordMessageAttachment {
|
|
|
|
var attachments []*protobuf.DiscordMessageAttachment
|
|
|
|
for _, a := range r.discordMessageAttachments {
|
|
|
|
attachments = append(attachments, a)
|
|
|
|
}
|
|
|
|
return attachments
|
|
|
|
}
|
|
|
|
|
2024-02-22 01:44:14 +00:00
|
|
|
// Messages extracts the messages from the response and returns them as a slice.
|
|
|
|
// Since 'r.messages' is a map, the order of messages in the resulting slice is not
|
|
|
|
// guaranteed and can vary with each call to this method. This is inherent to Go's map
|
|
|
|
// iteration behavior, which does not define a sequence for the order of map elements.
|
|
|
|
// Consumers should not depend on the ordering of messages in the slice for any logic
|
|
|
|
// that requires consistent ordering, as map iteration order can change when keys are
|
|
|
|
// added or deleted. Consider sorting the slice after retrieval if a specific order is needed.
|
2021-06-03 13:11:55 +00:00
|
|
|
func (r *MessengerResponse) Messages() []*common.Message {
|
|
|
|
var ms []*common.Message
|
|
|
|
for _, m := range r.messages {
|
|
|
|
ms = append(ms, m)
|
|
|
|
}
|
|
|
|
return ms
|
|
|
|
}
|
|
|
|
|
2022-09-29 11:50:23 +00:00
|
|
|
func (r *MessengerResponse) AddDiscordMessageAuthor(author *protobuf.DiscordMessageAuthor) {
|
|
|
|
if r.discordMessageAuthors == nil {
|
|
|
|
r.discordMessageAuthors = make(map[string]*protobuf.DiscordMessageAuthor)
|
|
|
|
}
|
|
|
|
r.discordMessageAuthors[author.Id] = author
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddDiscordMessageAttachment(attachment *protobuf.DiscordMessageAttachment) {
|
|
|
|
if r.discordMessageAttachments == nil {
|
|
|
|
r.discordMessageAttachments = make(map[string]*protobuf.DiscordMessageAttachment)
|
|
|
|
}
|
|
|
|
r.discordMessageAttachments[attachment.Id] = attachment
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddDiscordMessageAttachments(attachments []*protobuf.DiscordMessageAttachment) {
|
|
|
|
for _, attachment := range attachments {
|
|
|
|
r.AddDiscordMessageAttachment(attachment)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddDiscordMessage(message *protobuf.DiscordMessage) {
|
|
|
|
if r.discordMessages == nil {
|
|
|
|
r.discordMessages = make(map[string]*protobuf.DiscordMessage)
|
|
|
|
}
|
|
|
|
r.discordMessages[message.Id] = message
|
|
|
|
}
|
|
|
|
|
2021-06-03 13:11:55 +00:00
|
|
|
func (r *MessengerResponse) AddMessages(ms []*common.Message) {
|
|
|
|
for _, m := range ms {
|
|
|
|
r.AddMessage(m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-25 15:15:22 +00:00
|
|
|
func (r *MessengerResponse) AddMessage(message *common.Message) {
|
2021-06-03 13:11:55 +00:00
|
|
|
if r.messages == nil {
|
|
|
|
r.messages = make(map[string]*common.Message)
|
|
|
|
}
|
2021-08-13 17:10:32 +00:00
|
|
|
if message.Deleted {
|
|
|
|
return
|
|
|
|
}
|
2021-06-03 13:11:55 +00:00
|
|
|
r.messages[message.ID] = message
|
|
|
|
}
|
|
|
|
|
2022-01-18 16:31:34 +00:00
|
|
|
func (r *MessengerResponse) AddContact(c *Contact) {
|
|
|
|
|
|
|
|
for idx, c1 := range r.Contacts {
|
|
|
|
if c1.ID == c.ID {
|
|
|
|
r.Contacts[idx] = c
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.Contacts = append(r.Contacts, c)
|
|
|
|
}
|
|
|
|
|
2023-02-10 12:20:06 +00:00
|
|
|
func (r *MessengerResponse) AddContacts(contacts []*Contact) {
|
|
|
|
for idx := range contacts {
|
|
|
|
r.AddContact(contacts[idx])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 20:09:20 +00:00
|
|
|
func (r *MessengerResponse) AddInstallation(i *multidevice.Installation) {
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
if len(r.installations) == 0 {
|
|
|
|
r.installations = make(map[string]*multidevice.Installation)
|
2023-02-13 20:09:20 +00:00
|
|
|
}
|
feat(pairing)_: Fallback pairing seed (#5614) (#5627)
* feat(pairing)!: Add extra parameters and remove v2 compatibility
This commit includes the following changes:
I have added a flag to maintain 2.29 compatibility.
Breaking change in connection string
The local pairing code that was parsing the connection string had a few non-upgradable features:
It was strictly checking the number of parameters, throwing an error if the number was different. This made it impossible to add parameters to it without breaking.
It was strictly checking the version number. This made increasing the version number impossible as older client would just refuse to connect.
The code has been changed so that:
Two parameters have been added, installation-id and key-uid. Those are needed for the fallback flow.
I have also removed version from the payload, since it wasn't used.
This means that we don't support v1 anymore. V2 parsing is supported . Going forward there's a clear strategy on how to update the protocol (append parameters, don't change existing one).
https://www.youtube.com/watch?v=oyLBGkS5ICk Is a must watch video for understanding the strategy
Changed MessengerResponse to use internally a map of installations rather than an array (minor)
Just moving towards maps as arrays tend to lead to subtle bugs.
Moved pairing methods to messenger_pairing.go
Just moved some methods
Added 2 new methods for the fallback flow
FinishPairingThroughSeedPhraseProcess
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R29
EnableAndSyncInstallation
https://github.com/status-im/status-go/pull/5567/files#diff-1ad620b07fa3bd5fbc96c9f459d88829938a162bf1aaf41c61dea6e38b488d54R18
Flow for clients
Client A1 is logged in
Client A2 is logged out
Client A1 shows a QR code
Client A2 scans a QR code
If connection fails on A2, the user will be prompted to enter a seed phrase.
If the generated account matches the key-uid from the QR code, A2 should call FinishPairingThroughSeedPhraseProcess with the installation id passed in the QR code. This will send installation information over waku. The user should be shown its own installation id and prompted to check the other device.
Client A1 will receive new installation data through waku, if they are still on the qr code page, they should show a popup to the user showing the received installation id, and a way to Enable and Sync, which should call the EnableAndSyncInstallation endpoint. This should finish the fallback syncing flow.
Current issues
Currently I haven't tested that all the data is synced after finishing the flow. I see that the two devices are paired correctly, but for example the DisplayName is not changed on the receiving device. I haven't had time to look into it further.
* test_: add more test for connection string parser
* fix_: fix panic when parse old connection string
* test_: add comments for TestMessengerPairAfterSeedPhrase
* fix_: correct error description
* feat_:rename FinishPairingThroughSeedPhraseProcess to EnableInstallationAndPair
* fix_: delete leftover
* fix_: add UniqueKey method
* fix_: unify the response for InputConnectionStringForBootstrapping
* fix_: remove fields installationID and keyUID in GethStatusBackend
* fix_: rename messenger_pairing to messenger_pairing_and_syncing
---------
Co-authored-by: frank <lovefree103@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-07-30 16:03:43 +00:00
|
|
|
r.installations[i.UniqueKey()] = i
|
2023-02-13 20:09:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddInstallations(installations []*multidevice.Installation) {
|
|
|
|
for idx := range installations {
|
|
|
|
r.AddInstallation(installations[idx])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-03 13:11:55 +00:00
|
|
|
func (r *MessengerResponse) SetMessages(messages []*common.Message) {
|
|
|
|
r.messages = make(map[string]*common.Message)
|
|
|
|
r.AddMessages(messages)
|
2021-03-25 15:15:22 +00:00
|
|
|
}
|
2021-06-03 14:09:30 +00:00
|
|
|
|
|
|
|
func (r *MessengerResponse) GetMessage(messageID string) *common.Message {
|
|
|
|
if r.messages == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return r.messages[messageID]
|
|
|
|
}
|
feat: introduce messenger APIs to extract discord channels
As part of the new Discord <-> Status Community Import functionality,
we're adding an API that extracts all discord categories and channels
from a previously exported discord export file.
These APIs can be used in clients to show the user what categories and
channels will be imported later on.
There are two APIs:
1. `Messenger.ExtractDiscordCategoriesAndChannels(filesToimport
[]string) (*MessengerResponse, map[string]*discord.ImportError)`
This takes a list of exported discord export (JSON) files (typically one per
channel), reads them, and extracts the categories and channels into
dedicated data structures (`[]DiscordChannel` and `[]DiscordCategory`)
It also returns the oldest message timestamp found in all extracted
channels.
The API is synchronous and returns the extracted data as
a `*MessengerResponse`. This allows to make the API available
status-go's RPC interface.
The error case is a `map[string]*discord.ImportError` where each key
is a file path of a JSON file that we tried to extract data from, and
the value a `discord.ImportError` which holds an error message and an
error code, allowing for distinguishing between "critical" errors and
"non-critical" errors.
2. `Messenger.RequestExtractDiscordCategoriesAndChannels(filesToImport
[]string)`
This is the asynchronous counterpart to
`ExtractDiscordCategoriesAndChannels`. The reason this API has been
added is because discord servers can have a lot of message and
channel data, which causes `ExtractDiscordCategoriesAndChannels` to
block the thread for too long, making apps potentially feel like they
are stuck.
This API runs inside a go routine, eventually calls
`ExtractDiscordCategoriesAndChannels`, and then emits a newly
introduced `DiscordCategoriesAndChannelsExtractedSignal` that clients
can react to.
Failure of extraction has to be determined by the
`discord.ImportErrors` emitted by the signal.
**A note about exported discord history files**
We expect users to export their discord histories via the
[DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter/wiki/GUI%2C-CLI-and-Formats-explained#exportguild)
tool. The tool allows to export the data in different formats, such as
JSON, HTML and CSV.
We expect users to have their data exported as JSON.
Closes: https://github.com/status-im/status-desktop/issues/6690
2022-07-13 09:33:53 +00:00
|
|
|
|
|
|
|
func (r *MessengerResponse) AddDiscordCategory(dc *discord.Category) {
|
|
|
|
for idx, c := range r.DiscordCategories {
|
|
|
|
if dc.ID == c.ID {
|
|
|
|
r.DiscordCategories[idx] = dc
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.DiscordCategories = append(r.DiscordCategories, dc)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddDiscordChannel(dc *discord.Channel) {
|
|
|
|
for idx, c := range r.DiscordChannels {
|
|
|
|
if dc.ID == c.ID {
|
|
|
|
r.DiscordChannels[idx] = dc
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.DiscordChannels = append(r.DiscordChannels, dc)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) HasDiscordCategory(id string) bool {
|
|
|
|
for _, c := range r.DiscordCategories {
|
|
|
|
if id == c.ID {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) HasDiscordChannel(id string) bool {
|
|
|
|
for _, c := range r.DiscordChannels {
|
|
|
|
if id == c.ID {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2023-11-09 18:59:01 +00:00
|
|
|
|
2024-03-29 10:22:44 +00:00
|
|
|
func (r *MessengerResponse) AddSeveralUpdatedProfileShowcaseContactIDs(contactIDs []string) {
|
|
|
|
for _, contactID := range contactIDs {
|
|
|
|
r.AddUpdatedProfileShowcaseContactID(contactID)
|
2023-11-09 18:59:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-29 10:22:44 +00:00
|
|
|
func (r *MessengerResponse) AddUpdatedProfileShowcaseContactID(contactID string) {
|
|
|
|
if r.updatedProfileShowcaseContactIDs == nil {
|
|
|
|
r.updatedProfileShowcaseContactIDs = make(map[string]bool)
|
2023-11-09 18:59:01 +00:00
|
|
|
}
|
|
|
|
|
2024-03-29 10:22:44 +00:00
|
|
|
if _, exists := r.updatedProfileShowcaseContactIDs[contactID]; exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
r.updatedProfileShowcaseContactIDs[contactID] = true
|
2023-11-09 18:59:01 +00:00
|
|
|
}
|
|
|
|
|
2024-03-29 10:22:44 +00:00
|
|
|
func (r *MessengerResponse) GetUpdatedProfileShowcaseContactIDs() []string {
|
|
|
|
var contactIDs []string
|
|
|
|
for contactID := range r.updatedProfileShowcaseContactIDs {
|
|
|
|
contactIDs = append(contactIDs, contactID)
|
2023-11-09 18:59:01 +00:00
|
|
|
}
|
2024-03-29 10:22:44 +00:00
|
|
|
return contactIDs
|
2023-11-09 18:59:01 +00:00
|
|
|
}
|
2023-12-25 06:25:22 +00:00
|
|
|
|
|
|
|
func (r *MessengerResponse) AddSeveralSeenAndUnseenMessages(messages []*SeenUnseenMessages) {
|
|
|
|
for _, message := range messages {
|
|
|
|
r.AddSeenAndUnseenMessages(message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) AddSeenAndUnseenMessages(message *SeenUnseenMessages) {
|
|
|
|
if r.seenAndUnseenMessages == nil {
|
|
|
|
r.seenAndUnseenMessages = make(map[string]*SeenUnseenMessages)
|
|
|
|
}
|
|
|
|
|
|
|
|
r.seenAndUnseenMessages[message.ChatID] = message
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MessengerResponse) GetSeenAndUnseenMessages() []*SeenUnseenMessages {
|
|
|
|
var messages []*SeenUnseenMessages
|
|
|
|
for _, message := range r.seenAndUnseenMessages {
|
|
|
|
messages = append(messages, message)
|
|
|
|
}
|
|
|
|
return messages
|
|
|
|
}
|