github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/notify_router.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "fmt" 8 "sync" 9 "time" 10 11 "github.com/keybase/client/go/protocol/chat1" 12 "github.com/keybase/client/go/protocol/keybase1" 13 stellar1 "github.com/keybase/client/go/protocol/stellar1" 14 "github.com/keybase/go-framed-msgpack-rpc/rpc" 15 context "golang.org/x/net/context" 16 ) 17 18 // NotifyListener provides hooks for listening for when 19 // notifications are called. It is intended to simplify 20 // testing notifications. 21 type NotifyListener interface { 22 Logout() 23 Login(username string) 24 ClientOutOfDate(to, uri, msg string) 25 UserChanged(uid keybase1.UID) 26 TrackingChanged(uid keybase1.UID, username NormalizedUsername) 27 TrackingInfo(uid keybase1.UID, followers, followees []string) 28 FSOnlineStatusChanged(online bool) 29 FSActivity(activity keybase1.FSNotification) 30 FSPathUpdated(path string) 31 FSEditListResponse(arg keybase1.FSEditListArg) 32 FSSyncStatusResponse(arg keybase1.FSSyncStatusArg) 33 FSSyncEvent(arg keybase1.FSPathSyncStatus) 34 FSEditListRequest(arg keybase1.FSEditListRequest) 35 FSOverallSyncStatusChanged(arg keybase1.FolderSyncStatus) 36 FSFavoritesChanged() 37 FavoritesChanged(uid keybase1.UID) 38 FSSubscriptionNotify(arg keybase1.FSSubscriptionNotifyArg) 39 FSSubscriptionNotifyPath(arg keybase1.FSSubscriptionNotifyPathArg) 40 PaperKeyCached(uid keybase1.UID, encKID keybase1.KID, sigKID keybase1.KID) 41 KeyfamilyChanged(uid keybase1.UID) 42 NewChatActivity(uid keybase1.UID, activity chat1.ChatActivity, source chat1.ChatActivitySource) 43 NewChatKBFSFileEditActivity(uid keybase1.UID, activity chat1.ChatActivity) 44 ChatIdentifyUpdate(update keybase1.CanonicalTLFNameAndIDWithBreaks) 45 ChatTLFFinalize(uid keybase1.UID, convID chat1.ConversationID, 46 finalizeInfo chat1.ConversationFinalizeInfo) 47 ChatTLFResolve(uid keybase1.UID, convID chat1.ConversationID, 48 resolveInfo chat1.ConversationResolveInfo) 49 ChatInboxStale(uid keybase1.UID) 50 ChatThreadsStale(uid keybase1.UID, updates []chat1.ConversationStaleUpdate) 51 ChatInboxSynced(uid keybase1.UID, topicType chat1.TopicType, syncRes chat1.ChatSyncResult) 52 ChatInboxSyncStarted(uid keybase1.UID) 53 ChatTypingUpdate([]chat1.ConvTypingUpdate) 54 ChatJoinedConversation(uid keybase1.UID, convID chat1.ConversationID, conv *chat1.InboxUIItem) 55 ChatLeftConversation(uid keybase1.UID, convID chat1.ConversationID) 56 ChatResetConversation(uid keybase1.UID, convID chat1.ConversationID) 57 ChatSetConvRetention(uid keybase1.UID, convID chat1.ConversationID) 58 ChatSetTeamRetention(uid keybase1.UID, teamID keybase1.TeamID) 59 ChatSetConvSettings(uid keybase1.UID, convID chat1.ConversationID) 60 ChatSubteamRename(uid keybase1.UID, convIDs []chat1.ConversationID) 61 ChatKBFSToImpteamUpgrade(uid keybase1.UID, convID chat1.ConversationID) 62 ChatAttachmentUploadStart(uid keybase1.UID, convID chat1.ConversationID, outboxID chat1.OutboxID) 63 ChatAttachmentUploadProgress(uid keybase1.UID, convID chat1.ConversationID, outboxID chat1.OutboxID, 64 bytesComplete, bytesTotal int64) 65 ChatAttachmentDownloadProgress(uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, 66 bytesComplete, bytesTotal int64) 67 ChatAttachmentDownloadComplete(uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID) 68 ChatArchiveProgress(jobID chat1.ArchiveJobID, 69 messagesComplete, messagesTotal int64) 70 ChatArchiveComplete(jobID chat1.ArchiveJobID) 71 ChatPaymentInfo(uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, info chat1.UIPaymentInfo) 72 ChatRequestInfo(uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, info chat1.UIRequestInfo) 73 ChatPromptUnfurl(uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, domain string) 74 ChatConvUpdate(uid keybase1.UID, convID chat1.ConversationID) 75 ChatWelcomeMessageLoaded(teamID keybase1.TeamID, message chat1.WelcomeMessageDisplay) 76 ChatParticipantsInfo(participants map[chat1.ConvIDStr][]chat1.UIParticipant) 77 PGPKeyInSecretStoreFile() 78 BadgeState(badgeState keybase1.BadgeState) 79 ReachabilityChanged(r keybase1.Reachability) 80 TeamChangedByID(teamID keybase1.TeamID, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, latestHiddenSeqno keybase1.Seqno, source keybase1.TeamChangedSource) 81 TeamChangedByName(teamName string, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, latestHiddenSeqno keybase1.Seqno, source keybase1.TeamChangedSource) 82 TeamDeleted(teamID keybase1.TeamID) 83 TeamRoleMapChanged(version keybase1.UserTeamVersion) 84 UserBlocked(b keybase1.UserBlockedBody) 85 TeamExit(teamID keybase1.TeamID) 86 NewlyAddedToTeam(teamID keybase1.TeamID) 87 NewTeamEK(teamID keybase1.TeamID, generation keybase1.EkGeneration) 88 NewTeambotEK(teamID keybase1.TeamID, generation keybase1.EkGeneration) 89 TeambotEKNeeded(teamID keybase1.TeamID, botUID keybase1.UID, generation keybase1.EkGeneration, forceCreateGen *keybase1.EkGeneration) 90 NewTeambotKey(teamID keybase1.TeamID, generation keybase1.TeambotKeyGeneration) 91 TeambotKeyNeeded(teamID keybase1.TeamID, botUID keybase1.UID, generation keybase1.TeambotKeyGeneration) 92 AvatarUpdated(name string, formats []keybase1.AvatarFormat) 93 DeviceCloneCountChanged(newClones int) 94 WalletPaymentNotification(accountID stellar1.AccountID, paymentID stellar1.PaymentID) 95 WalletPaymentStatusNotification(accountID stellar1.AccountID, paymentID stellar1.PaymentID) 96 WalletRequestStatusNotification(reqID stellar1.KeybaseRequestID) 97 WalletAccountDetailsUpdate(accountID stellar1.AccountID, account stellar1.WalletAccountLocal) 98 WalletAccountsUpdate(accounts []stellar1.WalletAccountLocal) 99 WalletPendingPaymentsUpdate(accountID stellar1.AccountID, pending []stellar1.PaymentOrErrorLocal) 100 WalletRecentPaymentsUpdate(accountID stellar1.AccountID, firstPage stellar1.PaymentsPageLocal) 101 TeamMetadataUpdate() 102 CanUserPerformChanged(teamName string) 103 PhoneNumbersChanged(list []keybase1.UserPhoneNumber, category string, phoneNumber keybase1.PhoneNumber) 104 EmailAddressVerified(emailAddress keybase1.EmailAddress) 105 EmailsChanged(list []keybase1.Email, category string, email keybase1.EmailAddress) 106 PasswordChanged() 107 RootAuditError(msg string) 108 BoxAuditError(msg string) 109 RuntimeStatsUpdate(*keybase1.RuntimeStats) 110 HTTPSrvInfoUpdate(keybase1.HttpSrvInfo) 111 HandleKeybaseLink(link string, deferred bool) 112 IdentifyUpdate(okUsernames []string, brokenUsernames []string) 113 Reachability(keybase1.Reachability) 114 FeaturedBotsUpdate(bots []keybase1.FeaturedBot, limit, offset int) 115 SaltpackOperationStart(opType keybase1.SaltpackOperationType, filename string) 116 SaltpackOperationProgress(opType keybase1.SaltpackOperationType, filename string, bytesComplete, bytesTotal int64) 117 SaltpackOperationDone(opType keybase1.SaltpackOperationType, filename string) 118 UpdateInviteCounts(keybase1.InviteCounts) 119 TeamTreeMembershipsPartial(keybase1.TeamTreeMembership) 120 TeamTreeMembershipsDone(keybase1.TeamTreeMembershipsDoneResult) 121 WebOfTrustChanged(username string) 122 } 123 124 type NoopNotifyListener struct{} 125 126 var _ NotifyListener = (*NoopNotifyListener)(nil) 127 128 func (n *NoopNotifyListener) Logout() {} 129 func (n *NoopNotifyListener) Login(username string) {} 130 func (n *NoopNotifyListener) ClientOutOfDate(to, uri, msg string) {} 131 func (n *NoopNotifyListener) UserChanged(uid keybase1.UID) {} 132 func (n *NoopNotifyListener) TrackingChanged(uid keybase1.UID, username NormalizedUsername) {} 133 func (n *NoopNotifyListener) TrackingInfo(uid keybase1.UID, followers, followees []string) {} 134 func (n *NoopNotifyListener) FSOnlineStatusChanged(online bool) {} 135 func (n *NoopNotifyListener) FSOverallSyncStatusChanged(status keybase1.FolderSyncStatus) {} 136 func (n *NoopNotifyListener) FSFavoritesChanged() {} 137 func (n *NoopNotifyListener) FSActivity(activity keybase1.FSNotification) {} 138 func (n *NoopNotifyListener) FSPathUpdated(path string) {} 139 func (n *NoopNotifyListener) FSEditListResponse(arg keybase1.FSEditListArg) {} 140 func (n *NoopNotifyListener) FSSyncStatusResponse(arg keybase1.FSSyncStatusArg) {} 141 func (n *NoopNotifyListener) FSSyncEvent(arg keybase1.FSPathSyncStatus) {} 142 func (n *NoopNotifyListener) FSEditListRequest(arg keybase1.FSEditListRequest) {} 143 func (n *NoopNotifyListener) FavoritesChanged(uid keybase1.UID) {} 144 func (n *NoopNotifyListener) FSSubscriptionNotify(arg keybase1.FSSubscriptionNotifyArg) { 145 } 146 func (n *NoopNotifyListener) FSSubscriptionNotifyPath(arg keybase1.FSSubscriptionNotifyPathArg) { 147 } 148 func (n *NoopNotifyListener) PaperKeyCached(uid keybase1.UID, encKID keybase1.KID, sigKID keybase1.KID) { 149 } 150 func (n *NoopNotifyListener) KeyfamilyChanged(uid keybase1.UID) {} 151 func (n *NoopNotifyListener) NewChatActivity(uid keybase1.UID, activity chat1.ChatActivity, 152 source chat1.ChatActivitySource) { 153 } 154 func (n *NoopNotifyListener) NewChatKBFSFileEditActivity(uid keybase1.UID, activity chat1.ChatActivity) { 155 } 156 func (n *NoopNotifyListener) ChatIdentifyUpdate(update keybase1.CanonicalTLFNameAndIDWithBreaks) {} 157 func (n *NoopNotifyListener) ChatTLFFinalize(uid keybase1.UID, convID chat1.ConversationID, 158 finalizeInfo chat1.ConversationFinalizeInfo) { 159 } 160 func (n *NoopNotifyListener) ChatTLFResolve(uid keybase1.UID, convID chat1.ConversationID, 161 resolveInfo chat1.ConversationResolveInfo) { 162 } 163 func (n *NoopNotifyListener) ChatInboxStale(uid keybase1.UID) {} 164 func (n *NoopNotifyListener) ChatThreadsStale(uid keybase1.UID, updates []chat1.ConversationStaleUpdate) { 165 } 166 func (n *NoopNotifyListener) ChatInboxSynced(uid keybase1.UID, topicType chat1.TopicType, 167 syncRes chat1.ChatSyncResult) { 168 } 169 func (n *NoopNotifyListener) ChatInboxSyncStarted(uid keybase1.UID) {} 170 func (n *NoopNotifyListener) ChatTypingUpdate([]chat1.ConvTypingUpdate) {} 171 func (n *NoopNotifyListener) ChatJoinedConversation(uid keybase1.UID, convID chat1.ConversationID, 172 conv *chat1.InboxUIItem) { 173 } 174 func (n *NoopNotifyListener) ChatLeftConversation(uid keybase1.UID, convID chat1.ConversationID) {} 175 func (n *NoopNotifyListener) ChatResetConversation(uid keybase1.UID, convID chat1.ConversationID) {} 176 func (n *NoopNotifyListener) Chat(uid keybase1.UID, convID chat1.ConversationID) {} 177 func (n *NoopNotifyListener) ChatSetConvRetention(uid keybase1.UID, convID chat1.ConversationID) {} 178 func (n *NoopNotifyListener) ChatSetTeamRetention(uid keybase1.UID, teamID keybase1.TeamID) {} 179 func (n *NoopNotifyListener) ChatSetConvSettings(uid keybase1.UID, convID chat1.ConversationID) {} 180 func (n *NoopNotifyListener) ChatSubteamRename(uid keybase1.UID, convIDs []chat1.ConversationID) {} 181 func (n *NoopNotifyListener) ChatKBFSToImpteamUpgrade(uid keybase1.UID, convID chat1.ConversationID) { 182 } 183 func (n *NoopNotifyListener) ChatAttachmentUploadStart(uid keybase1.UID, convID chat1.ConversationID, 184 outboxID chat1.OutboxID) { 185 } 186 func (n *NoopNotifyListener) ChatAttachmentUploadProgress(uid keybase1.UID, convID chat1.ConversationID, 187 outboxID chat1.OutboxID, bytesComplete, bytesTotal int64) { 188 } 189 func (n *NoopNotifyListener) ChatAttachmentDownloadProgress(uid keybase1.UID, convID chat1.ConversationID, 190 msgID chat1.MessageID, bytesComplete, bytesTotal int64) { 191 } 192 func (n *NoopNotifyListener) ChatAttachmentDownloadComplete(uid keybase1.UID, convID chat1.ConversationID, 193 msgID chat1.MessageID) { 194 } 195 func (n *NoopNotifyListener) ChatArchiveProgress(jobID chat1.ArchiveJobID, messagesComplete, messagesTotal int64) { 196 } 197 func (n *NoopNotifyListener) ChatArchiveComplete(jobID chat1.ArchiveJobID) { 198 } 199 func (n *NoopNotifyListener) ChatPaymentInfo(uid keybase1.UID, convID chat1.ConversationID, 200 msgID chat1.MessageID, info chat1.UIPaymentInfo) { 201 } 202 func (n *NoopNotifyListener) ChatRequestInfo(uid keybase1.UID, convID chat1.ConversationID, 203 msgID chat1.MessageID, info chat1.UIRequestInfo) { 204 } 205 func (n *NoopNotifyListener) ChatPromptUnfurl(uid keybase1.UID, convID chat1.ConversationID, 206 msgID chat1.MessageID, domain string) { 207 } 208 func (n *NoopNotifyListener) ChatConvUpdate(uid keybase1.UID, convID chat1.ConversationID) {} 209 func (n *NoopNotifyListener) ChatWelcomeMessageLoaded(keybase1.TeamID, chat1.WelcomeMessageDisplay) {} 210 func (n *NoopNotifyListener) ChatParticipantsInfo( 211 participants map[chat1.ConvIDStr][]chat1.UIParticipant) { 212 } 213 214 func (n *NoopNotifyListener) PGPKeyInSecretStoreFile() {} 215 func (n *NoopNotifyListener) BadgeState(badgeState keybase1.BadgeState) {} 216 func (n *NoopNotifyListener) ReachabilityChanged(r keybase1.Reachability) {} 217 func (n *NoopNotifyListener) TeamChangedByID(teamID keybase1.TeamID, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, latestHiddenSeqno keybase1.Seqno, source keybase1.TeamChangedSource) { 218 } 219 func (n *NoopNotifyListener) TeamChangedByName(teamName string, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, latestHiddenSeqno keybase1.Seqno, source keybase1.TeamChangedSource) { 220 } 221 func (n *NoopNotifyListener) TeamDeleted(teamID keybase1.TeamID) {} 222 func (n *NoopNotifyListener) TeamExit(teamID keybase1.TeamID) {} 223 func (n *NoopNotifyListener) TeamRoleMapChanged(version keybase1.UserTeamVersion) {} 224 func (n *NoopNotifyListener) NewTeamEK(teamID keybase1.TeamID, generation keybase1.EkGeneration) {} 225 func (n *NoopNotifyListener) NewTeambotEK(teamID keybase1.TeamID, generation keybase1.EkGeneration) {} 226 func (n *NoopNotifyListener) TeambotEKNeeded(teamID keybase1.TeamID, botUID keybase1.UID, 227 generation keybase1.EkGeneration, forceCreateGen *keybase1.EkGeneration) { 228 } 229 func (n *NoopNotifyListener) NewTeambotKey(teamID keybase1.TeamID, generation keybase1.TeambotKeyGeneration) { 230 } 231 func (n *NoopNotifyListener) TeambotKeyNeeded(teamID keybase1.TeamID, botUID keybase1.UID, 232 generation keybase1.TeambotKeyGeneration) { 233 } 234 func (n *NoopNotifyListener) NewlyAddedToTeam(teamID keybase1.TeamID) {} 235 func (n *NoopNotifyListener) AvatarUpdated(name string, formats []keybase1.AvatarFormat) {} 236 func (n *NoopNotifyListener) DeviceCloneCountChanged(newClones int) {} 237 func (n *NoopNotifyListener) WalletPaymentNotification(accountID stellar1.AccountID, paymentID stellar1.PaymentID) { 238 } 239 func (n *NoopNotifyListener) WalletPaymentStatusNotification(accountID stellar1.AccountID, paymentID stellar1.PaymentID) { 240 } 241 func (n *NoopNotifyListener) WalletRequestStatusNotification(reqID stellar1.KeybaseRequestID) {} 242 func (n *NoopNotifyListener) WalletAccountDetailsUpdate(accountID stellar1.AccountID, account stellar1.WalletAccountLocal) { 243 } 244 func (n *NoopNotifyListener) WalletAccountsUpdate(accounts []stellar1.WalletAccountLocal) {} 245 func (n *NoopNotifyListener) WalletPendingPaymentsUpdate(accountID stellar1.AccountID, pending []stellar1.PaymentOrErrorLocal) { 246 } 247 func (n *NoopNotifyListener) WalletRecentPaymentsUpdate(accountID stellar1.AccountID, firstPage stellar1.PaymentsPageLocal) { 248 } 249 func (n *NoopNotifyListener) TeamMetadataUpdate() {} 250 func (n *NoopNotifyListener) CanUserPerformChanged(teamName string) {} 251 func (n *NoopNotifyListener) PhoneNumbersChanged(list []keybase1.UserPhoneNumber, category string, phoneNumber keybase1.PhoneNumber) { 252 } 253 func (n *NoopNotifyListener) EmailAddressVerified(emailAddress keybase1.EmailAddress) {} 254 func (n *NoopNotifyListener) EmailsChanged(list []keybase1.Email, category string, email keybase1.EmailAddress) { 255 } 256 func (n *NoopNotifyListener) PasswordChanged() {} 257 func (n *NoopNotifyListener) RootAuditError(msg string) {} 258 func (n *NoopNotifyListener) BoxAuditError(msg string) {} 259 func (n *NoopNotifyListener) RuntimeStatsUpdate(*keybase1.RuntimeStats) {} 260 func (n *NoopNotifyListener) HTTPSrvInfoUpdate(keybase1.HttpSrvInfo) {} 261 func (n *NoopNotifyListener) HandleKeybaseLink(link string, deferred bool) {} 262 func (n *NoopNotifyListener) IdentifyUpdate(okUsernames []string, brokenUsernames []string) { 263 } 264 func (n *NoopNotifyListener) Reachability(keybase1.Reachability) {} 265 func (n *NoopNotifyListener) UserBlocked(keybase1.UserBlockedBody) {} 266 func (n *NoopNotifyListener) FeaturedBotsUpdate(bots []keybase1.FeaturedBot, limit, offset int) {} 267 func (n *NoopNotifyListener) SaltpackOperationStart(opType keybase1.SaltpackOperationType, filename string) { 268 } 269 func (n *NoopNotifyListener) SaltpackOperationProgress(opType keybase1.SaltpackOperationType, filename string, bytesComplete, bytesTotal int64) { 270 } 271 func (n *NoopNotifyListener) SaltpackOperationDone(opType keybase1.SaltpackOperationType, filename string) { 272 } 273 func (n *NoopNotifyListener) UpdateInviteCounts(keybase1.InviteCounts) { 274 } 275 func (n *NoopNotifyListener) TeamTreeMembershipsPartial(keybase1.TeamTreeMembership) {} 276 func (n *NoopNotifyListener) TeamTreeMembershipsDone(keybase1.TeamTreeMembershipsDoneResult) {} 277 func (n *NoopNotifyListener) WebOfTrustChanged(username string) { 278 } 279 280 type NotifyListenerID string 281 282 // NotifyRouter routes notifications to the various active RPC 283 // connections. It's careful only to route to those who are interested 284 type NotifyRouter struct { 285 sync.Mutex 286 Contextified 287 cm *ConnectionManager 288 state map[ConnectionID]keybase1.NotificationChannels 289 listeners map[NotifyListenerID]NotifyListener 290 } 291 292 // NewNotifyRouter makes a new notification router; we should only 293 // make one of these per process. 294 func NewNotifyRouter(g *GlobalContext) *NotifyRouter { 295 return &NotifyRouter{ 296 Contextified: NewContextified(g), 297 cm: g.ConnectionManager, 298 state: make(map[ConnectionID]keybase1.NotificationChannels), 299 listeners: make(map[NotifyListenerID]NotifyListener), 300 } 301 } 302 303 func (n *NotifyRouter) AddListener(listener NotifyListener) NotifyListenerID { 304 n.Lock() 305 defer n.Unlock() 306 id := NotifyListenerID(RandStringB64(3)) 307 n.listeners[id] = listener 308 return id 309 } 310 311 func (n *NotifyRouter) RemoveListener(id NotifyListenerID) { 312 n.Lock() 313 defer n.Unlock() 314 delete(n.listeners, id) 315 } 316 317 func (n *NotifyRouter) Shutdown() {} 318 319 func (n *NotifyRouter) setNotificationChannels(id ConnectionID, val keybase1.NotificationChannels) { 320 n.Lock() 321 defer n.Unlock() 322 n.state[id] = val 323 } 324 325 func (n *NotifyRouter) getNotificationChannels(id ConnectionID) keybase1.NotificationChannels { 326 n.Lock() 327 defer n.Unlock() 328 return n.state[id] 329 } 330 331 // GetChannels retrieves which notification channels a connection is interested it 332 // given its ID. 333 func (n *NotifyRouter) GetChannels(i ConnectionID) keybase1.NotificationChannels { 334 return n.getNotificationChannels(i) 335 } 336 337 func (n *NotifyRouter) runListeners(f func(listener NotifyListener)) { 338 var listeners []NotifyListener 339 n.Lock() 340 for _, l := range n.listeners { 341 listeners = append(listeners, l) 342 } 343 n.Unlock() 344 for _, l := range listeners { 345 f(l) 346 } 347 } 348 349 // AddConnection should be called every time there's a new RPC connection 350 // established for this server. The caller should pass in the Transporter 351 // and also the channel that will get messages when the channel closes. 352 func (n *NotifyRouter) AddConnection(xp rpc.Transporter, ch chan error) ConnectionID { 353 if n == nil { 354 return 0 355 } 356 id := n.cm.AddConnection(xp, ch) 357 n.setNotificationChannels(id, keybase1.NotificationChannels{}) 358 return id 359 } 360 361 // SetChannels sets which notification channels are interested for the connection 362 // with the given connection ID. 363 func (n *NotifyRouter) SetChannels(i ConnectionID, nc keybase1.NotificationChannels) { 364 n.setNotificationChannels(i, nc) 365 } 366 367 // HandleLogout is called whenever the current user logged out. It will broadcast 368 // the message to all connections who care about such a message. 369 func (n *NotifyRouter) HandleLogout(ctx context.Context) { 370 if n == nil { 371 return 372 } 373 defer n.G().CTrace(ctx, "NotifyRouter#HandleLogout", nil)() 374 ctx = CopyTagsToBackground(ctx) 375 // For all connections we currently have open... 376 n.cm.ApplyAllDetails(func(id ConnectionID, xp rpc.Transporter, d *keybase1.ClientDetails) bool { 377 // If the connection wants the `Session` notification type 378 registered := false 379 if n.getNotificationChannels(id).Session { 380 registered = true 381 // In the background do... 382 go func() { 383 // A send of a `LoggedOut` RPC 384 _ = (keybase1.NotifySessionClient{ 385 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 386 }).LoggedOut(ctx) 387 }() 388 } 389 desc := "<nil>" 390 if d != nil { 391 desc = fmt.Sprintf("%+v", *d) 392 } 393 n.G().Log.CDebugf(ctx, "| NotifyRouter#HandleLogout: client %s (sent=%v)", desc, registered) 394 return true 395 }) 396 397 n.runListeners(func(listener NotifyListener) { 398 listener.Logout() 399 }) 400 } 401 402 // HandleLogin is called when a user logs in. 403 func (n *NotifyRouter) HandleLogin(ctx context.Context, u string) { 404 if n == nil { 405 return 406 } 407 n.G().Log.CDebugf(ctx, "+ Sending login notification for user %q", u) 408 n.SendLogin(ctx, u, false) 409 } 410 411 // HandleSignup is called when a user is signed up. It will broadcast a loggedIn 412 // notification with a flag to signify this was because of a signup. 413 func (n *NotifyRouter) HandleSignup(ctx context.Context, u string) { 414 if n == nil { 415 return 416 } 417 n.G().Log.CDebugf(ctx, "+ Sending login notification for signup, as user %q", u) 418 n.SendLogin(ctx, u, true) 419 } 420 421 // SendLogin is called whenever a user logs in. It will broadcast 422 // the message to all connections who care about such a message. 423 func (n *NotifyRouter) SendLogin(ctx context.Context, u string, signedUp bool) { 424 if n == nil { 425 return 426 } 427 n.G().Log.CDebugf(ctx, "+ Sending login notification, as user %q, signedUp %t", u, signedUp) 428 // For all connections we currently have open... 429 ctx = CopyTagsToBackground(ctx) 430 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 431 // If the connection wants the `Session` notification type 432 if n.getNotificationChannels(id).Session { 433 // In the background do... 434 go func() { 435 // A send of a `LoggedIn` RPC 436 _ = (keybase1.NotifySessionClient{ 437 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 438 }).LoggedIn(ctx, keybase1.LoggedInArg{ 439 Username: u, 440 SignedUp: signedUp, 441 }) 442 }() 443 } 444 return true 445 }) 446 447 n.runListeners(func(listener NotifyListener) { 448 listener.Login(u) 449 }) 450 n.G().Log.CDebugf(ctx, "- Login notification sent") 451 } 452 453 // ClientOutOfDate is called whenever the API server tells us our client is out 454 // of date. (This is done by adding special headers to every API response that 455 // an out-of-date client makes.) 456 func (n *NotifyRouter) HandleClientOutOfDate(upgradeTo, upgradeURI, upgradeMsg string) { 457 if n == nil { 458 return 459 } 460 n.G().Log.Debug("+ Sending client-out-of-date notification") 461 // For all connections we currently have open... 462 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 463 // If the connection wants the `Session` notification type 464 if n.getNotificationChannels(id).Session { 465 // In the background do... 466 go func() { 467 // A send of a `ClientOutOfDate` RPC 468 _ = (keybase1.NotifySessionClient{ 469 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 470 }).ClientOutOfDate(context.Background(), keybase1.ClientOutOfDateArg{ 471 UpgradeTo: upgradeTo, 472 UpgradeURI: upgradeURI, 473 UpgradeMsg: upgradeMsg, 474 }) 475 }() 476 } 477 return true 478 }) 479 n.runListeners(func(listener NotifyListener) { 480 listener.ClientOutOfDate(upgradeTo, upgradeURI, upgradeMsg) 481 }) 482 n.G().Log.Debug("- client-out-of-date notification sent") 483 } 484 485 // HandleUserChanged is called whenever we know that a given user has 486 // changed (and must be cache-busted). It will broadcast the messages 487 // to all curious listeners. NOTE: we now only do this for the current logged in user 488 func (n *NotifyRouter) HandleUserChanged(mctx MetaContext, uid keybase1.UID, reason string) { 489 if !mctx.G().GetMyUID().Equal(uid) { 490 // don't send these for anyone but the current logged in user, no one cares about anything 491 // about other users 492 return 493 } 494 mctx.Debug("Sending UserChanged notification %v '%v')", uid, reason) 495 if n == nil { 496 return 497 } 498 // For all connections we currently have open... 499 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 500 // If the connection wants the `Users` notification type 501 if n.getNotificationChannels(id).Users { 502 // In the background do... 503 go func() { 504 // A send of a `UserChanged` RPC with the user's UID 505 _ = (keybase1.NotifyUsersClient{ 506 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(mctx.G()), nil), 507 }).UserChanged(context.Background(), uid) 508 }() 509 } 510 return true 511 }) 512 n.runListeners(func(listener NotifyListener) { 513 listener.UserChanged(uid) 514 }) 515 } 516 517 // HandleTrackingChanged is called whenever we have a new tracking or 518 // untracking chain link related to a given user. It will broadcast the 519 // messages to all curious listeners. 520 // isTracking is set to true if current user is tracking uid. 521 func (n *NotifyRouter) HandleTrackingChanged(uid keybase1.UID, username NormalizedUsername, isTracking bool) { 522 if n == nil { 523 return 524 } 525 arg := keybase1.TrackingChangedArg{ 526 Uid: uid, 527 Username: username.String(), 528 IsTracking: isTracking, 529 } 530 // For all connections we currently have open... 531 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 532 // If the connection wants the `Tracking` notification type 533 if n.getNotificationChannels(id).Tracking { 534 // In the background do... 535 go func() { 536 // A send of a `TrackingChanged` RPC with the user's UID 537 _ = (keybase1.NotifyTrackingClient{ 538 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 539 }).TrackingChanged(context.Background(), arg) 540 }() 541 } 542 return true 543 }) 544 n.runListeners(func(listener NotifyListener) { 545 listener.TrackingChanged(uid, username) 546 }) 547 } 548 549 func (n *NotifyRouter) HandleWebOfTrustChanged(username string) { 550 if n == nil { 551 return 552 } 553 // For all connections we currently have open... 554 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 555 // If the connection wants the notification type 556 if n.getNotificationChannels(id).Tracking { 557 // In the background do... 558 go func() { 559 // A send of a `WebOfTrustChanged` RPC with the user's username 560 _ = (keybase1.NotifyUsersClient{ 561 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 562 }).WebOfTrustChanged(context.Background(), username) 563 }() 564 } 565 return true 566 }) 567 n.runListeners(func(listener NotifyListener) { 568 listener.WebOfTrustChanged(username) 569 }) 570 } 571 572 func (n *NotifyRouter) HandleTrackingInfo(arg keybase1.TrackingInfoArg) { 573 if n == nil { 574 return 575 } 576 // For all connections we currently have open... 577 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 578 // If the connection wants the `Tracking` notification type 579 if n.getNotificationChannels(id).Tracking { 580 // In the background do... 581 go func() { 582 // A send of a `TrackingInfo` RPC with the user's UID 583 _ = (keybase1.NotifyTrackingClient{ 584 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 585 }).TrackingInfo(context.Background(), arg) 586 }() 587 } 588 return true 589 }) 590 n.runListeners(func(listener NotifyListener) { 591 listener.TrackingInfo(arg.Uid, arg.Followers, arg.Followees) 592 }) 593 } 594 595 // HandleBadgeState is called whenever the badge state changes 596 // It will broadcast the messages to all curious listeners. 597 func (n *NotifyRouter) HandleBadgeState(badgeState keybase1.BadgeState) { 598 if n == nil { 599 return 600 } 601 n.G().Log.Debug("Sending BadgeState notification") 602 // For all connections we currently have open... 603 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 604 // If the connection wants the `Badges` notification type 605 if n.getNotificationChannels(id).Badges { 606 // In the background do... 607 go func() { 608 // A send of a `BadgeState` RPC with the badge state 609 _ = (keybase1.NotifyBadgesClient{ 610 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 611 }).BadgeState(context.Background(), badgeState) 612 }() 613 } 614 return true 615 }) 616 n.runListeners(func(listener NotifyListener) { 617 listener.BadgeState(badgeState) 618 }) 619 } 620 621 // HandleFSOnlineStatusChanged is called when KBFS's online status changes. It 622 // will broadcast the messages to all curious listeners. 623 func (n *NotifyRouter) HandleFSOnlineStatusChanged(online bool) { 624 if n == nil { 625 return 626 } 627 // For all connections we currently have open... 628 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 629 // If the connection wants the `kbfs` notification type 630 if n.getNotificationChannels(id).Kbfs { 631 // In the background do... 632 go func() { 633 // A send of a `FSOnlineStatusChanged` RPC with the 634 // notification 635 _ = (keybase1.NotifyFSClient{ 636 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 637 }).FSOnlineStatusChanged(context.Background(), online) 638 }() 639 } 640 return true 641 }) 642 n.runListeners(func(listener NotifyListener) { 643 listener.FSOnlineStatusChanged(online) 644 }) 645 } 646 647 // HandleFSOverallSyncStatusChanged is called when the overall sync status 648 // changes. It will broadcast the messages to all curious listeners. 649 func (n *NotifyRouter) HandleFSOverallSyncStatusChanged(status keybase1.FolderSyncStatus) { 650 if n == nil { 651 return 652 } 653 // For all connections we currently have open... 654 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 655 // If the connection wants the `kbfs` notification type 656 if n.getNotificationChannels(id).Kbfs { 657 // In the background do... 658 go func() { 659 // A send of a `FSOnlineStatusChanged` RPC with the 660 // notification 661 _ = (keybase1.NotifyFSClient{ 662 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 663 }).FSOverallSyncStatusChanged(context.Background(), status) 664 }() 665 } 666 return true 667 }) 668 n.runListeners(func(listener NotifyListener) { 669 listener.FSOverallSyncStatusChanged(status) 670 }) 671 } 672 673 // HandleFSFavoritesChanged is called when the overall sync status 674 // changes. It will broadcast the messages to all curious listeners. 675 func (n *NotifyRouter) HandleFSFavoritesChanged() { 676 if n == nil { 677 return 678 } 679 // For all connections we currently have open... 680 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 681 // If the connection wants the `kbfs` notification type 682 if n.getNotificationChannels(id).Kbfs { 683 // In the background do... 684 go func() { 685 // A send of a `FSFavoritesChanged` RPC with the 686 // notification 687 _ = (keybase1.NotifyFSClient{ 688 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 689 }).FSFavoritesChanged(context.Background()) 690 }() 691 } 692 return true 693 }) 694 n.runListeners(func(listener NotifyListener) { 695 listener.FSFavoritesChanged() 696 }) 697 } 698 699 // HandleFSActivity is called for any KBFS notification. It will broadcast the messages 700 // to all curious listeners. 701 func (n *NotifyRouter) HandleFSActivity(activity keybase1.FSNotification) { 702 if n == nil { 703 return 704 } 705 // For all connections we currently have open... 706 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 707 // If the connection wants the `Kbfsdesktop` notification type 708 if n.getNotificationChannels(id).Kbfsdesktop { 709 // In the background do... 710 go func() { 711 // A send of a `FSActivity` RPC with the notification 712 _ = (keybase1.NotifyFSClient{ 713 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 714 }).FSActivity(context.Background(), activity) 715 }() 716 } 717 return true 718 }) 719 n.runListeners(func(listener NotifyListener) { 720 listener.FSActivity(activity) 721 }) 722 } 723 724 // HandleFSPathUpdated is called for any path update notification. It 725 // will broadcast the messages to all curious listeners. 726 func (n *NotifyRouter) HandleFSPathUpdated(path string) { 727 if n == nil { 728 return 729 } 730 // For all connections we currently have open... 731 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 732 // If the connection wants the `Kbfs` notification type 733 if n.getNotificationChannels(id).Kbfs { 734 // In the background do... 735 go func() { 736 // A send of a `FSPathUpdated` RPC with the notification 737 _ = (keybase1.NotifyFSClient{ 738 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 739 }).FSPathUpdated(context.Background(), path) 740 }() 741 } 742 return true 743 }) 744 745 n.runListeners(func(listener NotifyListener) { 746 listener.FSPathUpdated(path) 747 }) 748 } 749 750 // HandleFSEditListResponse is called for KBFS edit list response notifications. 751 func (n *NotifyRouter) HandleFSEditListResponse(ctx context.Context, arg keybase1.FSEditListArg) { 752 if n == nil { 753 return 754 } 755 756 // We have to make sure the context survives until all subsequent 757 // RPCs launched in this method are done. So we wait until 758 // the last completes before returning. 759 var wg sync.WaitGroup 760 761 // For all connections we currently have open... 762 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 763 // If the connection wants the `Kbfslegacy` notification type 764 if n.getNotificationChannels(id).Kbfslegacy { 765 // In the background do... 766 wg.Add(1) 767 go func() { 768 // A send of a `FSEditListResponse` RPC with the notification 769 _ = (keybase1.NotifyFSClient{ 770 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 771 }).FSEditListResponse(context.Background(), keybase1.FSEditListResponseArg(arg)) 772 wg.Done() 773 }() 774 } 775 return true 776 }) 777 wg.Wait() 778 779 n.runListeners(func(listener NotifyListener) { 780 listener.FSEditListResponse(arg) 781 }) 782 } 783 784 // HandleFSEditListRequest is called for KBFS edit list request notifications. 785 func (n *NotifyRouter) HandleFSEditListRequest(ctx context.Context, arg keybase1.FSEditListRequest) { 786 if n == nil { 787 return 788 } 789 790 // See above 791 var wg sync.WaitGroup 792 793 // For all connections we currently have open... 794 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 795 // If the connection wants the `Kbfslegacy` notification type 796 if n.getNotificationChannels(id).Kbfslegacy { 797 wg.Add(1) 798 // In the background do... 799 go func() { 800 // A send of a `FSEditListRequest` RPC with the notification 801 _ = (keybase1.NotifyFSRequestClient{ 802 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 803 }).FSEditListRequest(context.Background(), arg) 804 wg.Done() 805 }() 806 } 807 return true 808 }) 809 810 wg.Wait() 811 812 n.runListeners(func(listener NotifyListener) { 813 listener.FSEditListRequest(arg) 814 }) 815 } 816 817 // HandleFSSyncStatus is called for KBFS sync status notifications. 818 func (n *NotifyRouter) HandleFSSyncStatus(ctx context.Context, arg keybase1.FSSyncStatusArg) { 819 if n == nil { 820 return 821 } 822 // For all connections we currently have open... 823 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 824 // If the connection wants the `Kbfslegacy` notification type 825 if n.getNotificationChannels(id).Kbfslegacy { 826 // In the background do... 827 go func() { 828 // A send of a `FSSyncStatusResponse` RPC with the notification 829 _ = (keybase1.NotifyFSClient{ 830 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 831 }).FSSyncStatusResponse(context.Background(), keybase1.FSSyncStatusResponseArg(arg)) 832 }() 833 } 834 return true 835 }) 836 837 n.runListeners(func(listener NotifyListener) { 838 listener.FSSyncStatusResponse(arg) 839 }) 840 } 841 842 // HandleFSSyncEvent is called for KBFS sync event notifications. 843 func (n *NotifyRouter) HandleFSSyncEvent(ctx context.Context, arg keybase1.FSPathSyncStatus) { 844 if n == nil { 845 return 846 } 847 // For all connections we currently have open... 848 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 849 // If the connection wants the `Kbfs` notification type 850 if n.getNotificationChannels(id).Kbfs { 851 // In the background do... 852 go func() { 853 // A send of a `FSSyncActivity` RPC with the notification 854 _ = (keybase1.NotifyFSClient{ 855 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 856 }).FSSyncActivity(context.Background(), arg) 857 }() 858 } 859 return true 860 }) 861 n.runListeners(func(listener NotifyListener) { 862 listener.FSSyncEvent(arg) 863 }) 864 } 865 866 // HandleFavoritesChanged is called whenever the kbfs favorites change 867 // for a user (and caches should be invalidated). It will broadcast the 868 // messages to all curious listeners. 869 func (n *NotifyRouter) HandleFavoritesChanged(uid keybase1.UID) { 870 if n == nil { 871 return 872 } 873 874 n.G().Log.Debug("+ Sending favorites changed notification") 875 // For all connections we currently have open... 876 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 877 // If the connection wants the `Favorites` notification type 878 if n.getNotificationChannels(id).Favorites { 879 // In the background do... 880 go func() { 881 // A send of a `FavoritesChanged` RPC with the user's UID 882 _ = (keybase1.NotifyFavoritesClient{ 883 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 884 }).FavoritesChanged(context.Background(), uid) 885 }() 886 } 887 return true 888 }) 889 890 n.runListeners(func(listener NotifyListener) { 891 listener.FavoritesChanged(uid) 892 }) 893 n.G().Log.Debug("- Sent favorites changed notification") 894 } 895 896 func (n *NotifyRouter) HandleFSSubscriptionNotify(arg keybase1.FSSubscriptionNotifyArg) { 897 if n == nil { 898 return 899 } 900 // For all connections we currently have open... 901 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 902 // If the connection wants the `Kbfs` notification type 903 if n.getNotificationChannels(id).Kbfssubscription { 904 // In the background do... 905 go func() { 906 // A send of a `FSSyncActivity` RPC with the notification 907 _ = (keybase1.NotifyFSClient{ 908 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 909 }).FSSubscriptionNotify(context.Background(), arg) 910 }() 911 } 912 return true 913 }) 914 n.runListeners(func(listener NotifyListener) { 915 listener.FSSubscriptionNotify(arg) 916 }) 917 } 918 919 func (n *NotifyRouter) HandleFSSubscriptionNotifyPath(arg keybase1.FSSubscriptionNotifyPathArg) { 920 if n == nil { 921 return 922 } 923 // For all connections we currently have open... 924 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 925 // If the connection wants the `Kbfs` notification type 926 if n.getNotificationChannels(id).Kbfssubscription { 927 // In the background do... 928 go func() { 929 // A send of a `FSSyncActivity` RPC with the notification 930 _ = (keybase1.NotifyFSClient{ 931 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 932 }).FSSubscriptionNotifyPath(context.Background(), arg) 933 }() 934 } 935 return true 936 }) 937 n.runListeners(func(listener NotifyListener) { 938 listener.FSSubscriptionNotifyPath(arg) 939 }) 940 } 941 942 // HandleDeviceCloneNotification is called when a run of the device clone status update 943 // finds a newly-added, possible clone. It will broadcast the messages to all curious listeners. 944 func (n *NotifyRouter) HandleDeviceCloneNotification(newClones int) { 945 if n == nil { 946 return 947 } 948 949 n.G().Log.Debug("+ Sending device clone notification") 950 // For all connections we currently have open... 951 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 952 // If the connection wants the `Deviceclone` notification type 953 if n.getNotificationChannels(id).Deviceclone { 954 // In the background do... 955 go func() { 956 // A send of a `DeviceCloneCountChanged` RPC with the number of newly discovered clones 957 _ = (keybase1.NotifyDeviceCloneClient{ 958 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 959 }).DeviceCloneCountChanged(context.Background(), newClones) 960 }() 961 } 962 return true 963 }) 964 965 n.runListeners(func(listener NotifyListener) { 966 listener.DeviceCloneCountChanged(newClones) 967 }) 968 n.G().Log.Debug("- Sent device clone notification") 969 } 970 971 // canSkipNotification checks if the notification can be ignored and the given 972 // connection allows skips. 973 func (n *NotifyRouter) canSkipNotif(id ConnectionID, canSkip bool) bool { 974 return canSkip && n.getNotificationChannels(id).AllowChatNotifySkips 975 } 976 977 func (n *NotifyRouter) shouldSendChatNotification(id ConnectionID, topicType chat1.TopicType) bool { 978 switch topicType { 979 case chat1.TopicType_CHAT: 980 return n.getNotificationChannels(id).Chat 981 case chat1.TopicType_DEV: 982 return n.getNotificationChannels(id).Chatdev 983 case chat1.TopicType_KBFSFILEEDIT: 984 return n.getNotificationChannels(id).Chatkbfsedits 985 case chat1.TopicType_EMOJI: 986 return n.getNotificationChannels(id).Chatemoji 987 case chat1.TopicType_EMOJICROSS: 988 return n.getNotificationChannels(id).Chatemojicross 989 case chat1.TopicType_NONE: 990 return n.getNotificationChannels(id).Chat || 991 n.getNotificationChannels(id).Chatdev || 992 n.getNotificationChannels(id).Chatkbfsedits || 993 n.getNotificationChannels(id).Chatemoji || 994 n.getNotificationChannels(id).Chatemojicross 995 } 996 return false 997 } 998 999 func (n *NotifyRouter) HandleNewChatActivity(ctx context.Context, uid keybase1.UID, 1000 topicType chat1.TopicType, activity *chat1.ChatActivity, source chat1.ChatActivitySource, canSkip bool) { 1001 if n == nil { 1002 return 1003 } 1004 var wg sync.WaitGroup 1005 n.G().Log.CDebugf(ctx, "+ Sending NewChatActivity %v notification", source) 1006 // For all connections we currently have open... 1007 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1008 // If the connection wants the `Chat` notification type 1009 if n.shouldSendChatNotification(id, topicType) && !n.canSkipNotif(id, canSkip) { 1010 wg.Add(1) 1011 // In the background do... 1012 go func() { 1013 // A send of a `NewChatActivity` RPC with the user's UID 1014 _ = (chat1.NotifyChatClient{ 1015 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1016 }).NewChatActivity(context.Background(), chat1.NewChatActivityArg{ 1017 Uid: uid, 1018 Activity: *activity, 1019 Source: source, 1020 }) 1021 wg.Done() 1022 }() 1023 } 1024 return true 1025 }) 1026 wg.Wait() 1027 1028 n.runListeners(func(listener NotifyListener) { 1029 listener.NewChatActivity(uid, *activity, source) 1030 }) 1031 n.G().Log.CDebugf(ctx, "- Sent NewChatActivity notification") 1032 } 1033 1034 func (n *NotifyRouter) HandleChatIdentifyUpdate(ctx context.Context, update keybase1.CanonicalTLFNameAndIDWithBreaks) { 1035 if n == nil { 1036 return 1037 } 1038 var wg sync.WaitGroup 1039 n.G().Log.CDebugf(ctx, "+ Sending ChatIdentifyUpdate notification") 1040 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1041 if n.shouldSendChatNotification(id, chat1.TopicType_CHAT) { 1042 wg.Add(1) 1043 go func() { 1044 _ = (chat1.NotifyChatClient{ 1045 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1046 }).ChatIdentifyUpdate(context.Background(), update) 1047 wg.Done() 1048 }() 1049 } 1050 return true 1051 }) 1052 wg.Wait() 1053 1054 n.runListeners(func(listener NotifyListener) { 1055 listener.ChatIdentifyUpdate(update) 1056 }) 1057 n.G().Log.CDebugf(ctx, "- Sent ChatIdentifyUpdate notification") 1058 } 1059 1060 func (n *NotifyRouter) HandleChatTLFFinalize(ctx context.Context, uid keybase1.UID, 1061 convID chat1.ConversationID, topicType chat1.TopicType, finalizeInfo chat1.ConversationFinalizeInfo, 1062 conv *chat1.InboxUIItem) { 1063 if n == nil { 1064 return 1065 } 1066 var wg sync.WaitGroup 1067 n.G().Log.CDebugf(ctx, "+ Sending ChatTLFFinalize notification") 1068 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1069 if n.shouldSendChatNotification(id, topicType) { 1070 wg.Add(1) 1071 go func() { 1072 _ = (chat1.NotifyChatClient{ 1073 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1074 }).ChatTLFFinalize(context.Background(), chat1.ChatTLFFinalizeArg{ 1075 Uid: uid, 1076 ConvID: convID, 1077 FinalizeInfo: finalizeInfo, 1078 Conv: conv, 1079 }) 1080 wg.Done() 1081 }() 1082 } 1083 return true 1084 }) 1085 wg.Wait() 1086 1087 n.runListeners(func(listener NotifyListener) { 1088 listener.ChatTLFFinalize(uid, convID, finalizeInfo) 1089 }) 1090 n.G().Log.CDebugf(ctx, "- Sent ChatTLFFinalize notification") 1091 } 1092 1093 func (n *NotifyRouter) HandleChatTLFResolve(ctx context.Context, uid keybase1.UID, 1094 convID chat1.ConversationID, topicType chat1.TopicType, resolveInfo chat1.ConversationResolveInfo) { 1095 if n == nil { 1096 return 1097 } 1098 var wg sync.WaitGroup 1099 n.G().Log.CDebugf(ctx, "+ Sending ChatTLFResolve notification") 1100 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1101 if n.shouldSendChatNotification(id, topicType) { 1102 wg.Add(1) 1103 go func() { 1104 _ = (chat1.NotifyChatClient{ 1105 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1106 }).ChatTLFResolve(context.Background(), chat1.ChatTLFResolveArg{ 1107 Uid: uid, 1108 ConvID: convID, 1109 ResolveInfo: resolveInfo, 1110 }) 1111 wg.Done() 1112 }() 1113 } 1114 return true 1115 }) 1116 wg.Wait() 1117 1118 n.runListeners(func(listener NotifyListener) { 1119 listener.ChatTLFResolve(uid, convID, resolveInfo) 1120 }) 1121 n.G().Log.CDebugf(ctx, "- Sent ChatTLFResolve notification") 1122 } 1123 1124 func (n *NotifyRouter) HandleChatInboxStale(ctx context.Context, uid keybase1.UID) { 1125 if n == nil { 1126 return 1127 } 1128 var wg sync.WaitGroup 1129 n.G().Log.CDebugf(ctx, "+ Sending ChatInboxStale notification") 1130 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1131 if n.shouldSendChatNotification(id, chat1.TopicType_NONE) { 1132 wg.Add(1) 1133 go func() { 1134 _ = (chat1.NotifyChatClient{ 1135 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1136 }).ChatInboxStale(context.Background(), uid) 1137 wg.Done() 1138 }() 1139 } 1140 return true 1141 }) 1142 wg.Wait() 1143 1144 n.runListeners(func(listener NotifyListener) { 1145 listener.ChatInboxStale(uid) 1146 }) 1147 n.G().Log.CDebugf(ctx, "- Sent ChatInboxStale notification") 1148 } 1149 1150 func (n *NotifyRouter) HandleChatThreadsStale(ctx context.Context, uid keybase1.UID, 1151 updates []chat1.ConversationStaleUpdate) { 1152 if n == nil { 1153 return 1154 } 1155 var wg sync.WaitGroup 1156 n.G().Log.CDebugf(ctx, "+ Sending ChatThreadsStale notification") 1157 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1158 if n.shouldSendChatNotification(id, chat1.TopicType_NONE) { 1159 wg.Add(1) 1160 go func() { 1161 _ = (chat1.NotifyChatClient{ 1162 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1163 }).ChatThreadsStale(context.Background(), chat1.ChatThreadsStaleArg{ 1164 Uid: uid, 1165 Updates: updates, 1166 }) 1167 wg.Done() 1168 }() 1169 } 1170 return true 1171 }) 1172 wg.Wait() 1173 1174 n.runListeners(func(listener NotifyListener) { 1175 listener.ChatThreadsStale(uid, updates) 1176 }) 1177 n.G().Log.CDebugf(ctx, "- Sent ChatThreadsStale notification") 1178 } 1179 1180 func (n *NotifyRouter) HandleChatInboxSynced(ctx context.Context, uid keybase1.UID, 1181 topicType chat1.TopicType, syncRes chat1.ChatSyncResult) { 1182 if n == nil { 1183 return 1184 } 1185 var wg sync.WaitGroup 1186 typ, _ := syncRes.SyncType() 1187 n.G().Log.CDebugf(ctx, "+ Sending ChatInboxSynced notification: syncTyp: %v topicType: %v", typ, topicType) 1188 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1189 if n.shouldSendChatNotification(id, topicType) { 1190 wg.Add(1) 1191 go func() { 1192 _ = (chat1.NotifyChatClient{ 1193 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1194 }).ChatInboxSynced(context.Background(), chat1.ChatInboxSyncedArg{ 1195 Uid: uid, 1196 SyncRes: syncRes, 1197 }) 1198 wg.Done() 1199 }() 1200 } 1201 return true 1202 }) 1203 wg.Wait() 1204 1205 n.runListeners(func(listener NotifyListener) { 1206 listener.ChatInboxSynced(uid, topicType, syncRes) 1207 }) 1208 n.G().Log.CDebugf(ctx, "- Sent ChatInboxSynced notification") 1209 } 1210 1211 func (n *NotifyRouter) HandleChatInboxSyncStarted(ctx context.Context, uid keybase1.UID) { 1212 if n == nil { 1213 return 1214 } 1215 var wg sync.WaitGroup 1216 n.G().Log.CDebugf(ctx, "+ Sending ChatInboxSyncStarted notification") 1217 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1218 if n.shouldSendChatNotification(id, chat1.TopicType_NONE) { 1219 wg.Add(1) 1220 go func() { 1221 _ = (chat1.NotifyChatClient{ 1222 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1223 }).ChatInboxSyncStarted(context.Background(), uid) 1224 wg.Done() 1225 }() 1226 } 1227 return true 1228 }) 1229 wg.Wait() 1230 1231 n.runListeners(func(listener NotifyListener) { 1232 listener.ChatInboxSyncStarted(uid) 1233 }) 1234 n.G().Log.CDebugf(ctx, "- Sent ChatInboxSyncStarted notification") 1235 } 1236 1237 func (n *NotifyRouter) HandleChatTypingUpdate(ctx context.Context, updates []chat1.ConvTypingUpdate) { 1238 if n == nil { 1239 return 1240 } 1241 var wg sync.WaitGroup 1242 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1243 if n.shouldSendChatNotification(id, chat1.TopicType_CHAT) { 1244 wg.Add(1) 1245 go func() { 1246 _ = (chat1.NotifyChatClient{ 1247 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1248 }).ChatTypingUpdate(context.Background(), updates) 1249 wg.Done() 1250 }() 1251 } 1252 return true 1253 }) 1254 wg.Wait() 1255 1256 n.runListeners(func(listener NotifyListener) { 1257 listener.ChatTypingUpdate(updates) 1258 }) 1259 } 1260 1261 func (n *NotifyRouter) HandleChatJoinedConversation(ctx context.Context, uid keybase1.UID, 1262 convID chat1.ConversationID, topicType chat1.TopicType, conv *chat1.InboxUIItem) { 1263 if n == nil { 1264 return 1265 } 1266 var wg sync.WaitGroup 1267 n.G().Log.CDebugf(ctx, "+ Sending ChatJoinedConversation notification") 1268 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1269 if n.shouldSendChatNotification(id, topicType) { 1270 wg.Add(1) 1271 go func() { 1272 _ = (chat1.NotifyChatClient{ 1273 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1274 }).ChatJoinedConversation(context.Background(), chat1.ChatJoinedConversationArg{ 1275 Uid: uid, 1276 ConvID: convID, 1277 Conv: conv, 1278 }) 1279 wg.Done() 1280 }() 1281 } 1282 return true 1283 }) 1284 wg.Wait() 1285 1286 n.runListeners(func(listener NotifyListener) { 1287 listener.ChatJoinedConversation(uid, convID, conv) 1288 }) 1289 n.G().Log.CDebugf(ctx, "- Sent ChatJoinedConversation notification") 1290 } 1291 1292 func (n *NotifyRouter) HandleChatLeftConversation(ctx context.Context, uid keybase1.UID, 1293 convID chat1.ConversationID, topicType chat1.TopicType) { 1294 if n == nil { 1295 return 1296 } 1297 var wg sync.WaitGroup 1298 n.G().Log.CDebugf(ctx, "+ Sending ChatLeftConversation notification") 1299 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1300 if n.shouldSendChatNotification(id, topicType) { 1301 wg.Add(1) 1302 go func() { 1303 _ = (chat1.NotifyChatClient{ 1304 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1305 }).ChatLeftConversation(context.Background(), chat1.ChatLeftConversationArg{ 1306 Uid: uid, 1307 ConvID: convID, 1308 }) 1309 wg.Done() 1310 }() 1311 } 1312 return true 1313 }) 1314 wg.Wait() 1315 n.runListeners(func(listener NotifyListener) { 1316 listener.ChatLeftConversation(uid, convID) 1317 }) 1318 n.G().Log.CDebugf(ctx, "- Sent ChatLeftConversation notification") 1319 } 1320 1321 func (n *NotifyRouter) HandleChatResetConversation(ctx context.Context, uid keybase1.UID, 1322 convID chat1.ConversationID, topicType chat1.TopicType) { 1323 if n == nil { 1324 return 1325 } 1326 var wg sync.WaitGroup 1327 n.G().Log.CDebugf(ctx, "+ Sending ChatResetConversation notification") 1328 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1329 if n.shouldSendChatNotification(id, topicType) { 1330 wg.Add(1) 1331 go func() { 1332 _ = (chat1.NotifyChatClient{ 1333 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1334 }).ChatResetConversation(context.Background(), chat1.ChatResetConversationArg{ 1335 Uid: uid, 1336 ConvID: convID, 1337 }) 1338 wg.Done() 1339 }() 1340 } 1341 return true 1342 }) 1343 wg.Wait() 1344 1345 n.runListeners(func(listener NotifyListener) { 1346 listener.ChatResetConversation(uid, convID) 1347 }) 1348 n.G().Log.CDebugf(ctx, "- Sent ChatResetConversation notification") 1349 } 1350 1351 func (n *NotifyRouter) HandleChatKBFSToImpteamUpgrade(ctx context.Context, uid keybase1.UID, 1352 convID chat1.ConversationID, topicType chat1.TopicType) { 1353 if n == nil { 1354 return 1355 } 1356 var wg sync.WaitGroup 1357 n.G().Log.CDebugf(ctx, "+ Sending ChatKBFSToImpteamUpgrade notification") 1358 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1359 if n.shouldSendChatNotification(id, topicType) { 1360 wg.Add(1) 1361 go func() { 1362 _ = (chat1.NotifyChatClient{ 1363 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1364 }).ChatKBFSToImpteamUpgrade(context.Background(), chat1.ChatKBFSToImpteamUpgradeArg{ 1365 Uid: uid, 1366 ConvID: convID, 1367 }) 1368 wg.Done() 1369 }() 1370 } 1371 return true 1372 }) 1373 wg.Wait() 1374 1375 n.runListeners(func(listener NotifyListener) { 1376 listener.ChatKBFSToImpteamUpgrade(uid, convID) 1377 }) 1378 n.G().Log.CDebugf(ctx, "- Sent ChatKBFSToImpteamUpgrade notification") 1379 } 1380 1381 func (n *NotifyRouter) HandleChatAttachmentUploadStart(ctx context.Context, uid keybase1.UID, 1382 convID chat1.ConversationID, outboxID chat1.OutboxID) { 1383 if n == nil { 1384 return 1385 } 1386 var wg sync.WaitGroup 1387 n.G().Log.CDebugf(ctx, "+ Sending ChatAttachmentUploadStart notification") 1388 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1389 if n.getNotificationChannels(id).Chatattachments { 1390 wg.Add(1) 1391 go func() { 1392 _ = (chat1.NotifyChatClient{ 1393 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1394 }).ChatAttachmentUploadStart(context.Background(), chat1.ChatAttachmentUploadStartArg{ 1395 Uid: uid, 1396 ConvID: convID, 1397 OutboxID: outboxID, 1398 }) 1399 wg.Done() 1400 }() 1401 } 1402 return true 1403 }) 1404 wg.Wait() 1405 1406 n.runListeners(func(listener NotifyListener) { 1407 listener.ChatAttachmentUploadStart(uid, convID, outboxID) 1408 }) 1409 n.G().Log.CDebugf(ctx, "- Sent ChatAttachmentUploadStart notification") 1410 } 1411 1412 func (n *NotifyRouter) HandleChatAttachmentUploadProgress(ctx context.Context, uid keybase1.UID, 1413 convID chat1.ConversationID, outboxID chat1.OutboxID, bytesComplete, bytesTotal int64) { 1414 if n == nil { 1415 return 1416 } 1417 var wg sync.WaitGroup 1418 n.G().Log.CDebugf(ctx, "+ Sending ChatAttachmentUploadProgress notification") 1419 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1420 if n.getNotificationChannels(id).Chatattachments { 1421 wg.Add(1) 1422 go func() { 1423 _ = (chat1.NotifyChatClient{ 1424 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1425 }).ChatAttachmentUploadProgress(context.Background(), chat1.ChatAttachmentUploadProgressArg{ 1426 Uid: uid, 1427 ConvID: convID, 1428 OutboxID: outboxID, 1429 BytesComplete: bytesComplete, 1430 BytesTotal: bytesTotal, 1431 }) 1432 wg.Done() 1433 }() 1434 } 1435 return true 1436 }) 1437 wg.Wait() 1438 1439 n.runListeners(func(listener NotifyListener) { 1440 listener.ChatAttachmentUploadProgress(uid, convID, outboxID, bytesComplete, bytesTotal) 1441 }) 1442 n.G().Log.CDebugf(ctx, "- Sent ChatAttachmentUploadProgress notification") 1443 } 1444 1445 func (n *NotifyRouter) HandleChatAttachmentDownloadProgress(ctx context.Context, uid keybase1.UID, 1446 convID chat1.ConversationID, msgID chat1.MessageID, bytesComplete, bytesTotal int64) { 1447 if n == nil { 1448 return 1449 } 1450 var wg sync.WaitGroup 1451 n.G().Log.CDebugf(ctx, "+ Sending ChatAttachmentDownloadProgress notification") 1452 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1453 if n.getNotificationChannels(id).Chatattachments { 1454 wg.Add(1) 1455 go func() { 1456 _ = (chat1.NotifyChatClient{ 1457 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1458 }).ChatAttachmentDownloadProgress(context.Background(), chat1.ChatAttachmentDownloadProgressArg{ 1459 Uid: uid, 1460 ConvID: convID, 1461 MsgID: msgID, 1462 BytesComplete: bytesComplete, 1463 BytesTotal: bytesTotal, 1464 }) 1465 wg.Done() 1466 }() 1467 } 1468 return true 1469 }) 1470 wg.Wait() 1471 1472 n.runListeners(func(listener NotifyListener) { 1473 listener.ChatAttachmentDownloadProgress(uid, convID, msgID, bytesComplete, bytesTotal) 1474 }) 1475 n.G().Log.CDebugf(ctx, "- Sent ChatAttachmentDownloadProgress notification") 1476 } 1477 1478 func (n *NotifyRouter) HandleChatAttachmentDownloadComplete(ctx context.Context, uid keybase1.UID, 1479 convID chat1.ConversationID, msgID chat1.MessageID) { 1480 if n == nil { 1481 return 1482 } 1483 var wg sync.WaitGroup 1484 n.G().Log.CDebugf(ctx, "+ Sending ChatAttachmentDownloadComplete notification") 1485 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1486 if n.getNotificationChannels(id).Chatattachments { 1487 wg.Add(1) 1488 go func() { 1489 _ = (chat1.NotifyChatClient{ 1490 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1491 }).ChatAttachmentDownloadComplete(context.Background(), chat1.ChatAttachmentDownloadCompleteArg{ 1492 Uid: uid, 1493 ConvID: convID, 1494 MsgID: msgID, 1495 }) 1496 wg.Done() 1497 }() 1498 } 1499 return true 1500 }) 1501 wg.Wait() 1502 1503 n.runListeners(func(listener NotifyListener) { 1504 listener.ChatAttachmentDownloadComplete(uid, convID, msgID) 1505 }) 1506 n.G().Log.CDebugf(ctx, "- Sent ChatAttachmentDownloadComplete notification") 1507 } 1508 1509 func (n *NotifyRouter) HandleChatArchiveProgress(ctx context.Context, jobID chat1.ArchiveJobID, messagesComplete, messagesTotal int64) { 1510 if n == nil { 1511 return 1512 } 1513 var wg sync.WaitGroup 1514 n.G().Log.CDebugf(ctx, "+ Sending ChatArchiveProgress notification") 1515 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1516 if n.getNotificationChannels(id).Chatarchive { 1517 wg.Add(1) 1518 go func() { 1519 _ = (chat1.NotifyChatClient{ 1520 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1521 }).ChatArchiveProgress(context.Background(), chat1.ChatArchiveProgressArg{ 1522 JobID: jobID, 1523 MessagesComplete: messagesComplete, 1524 MessagesTotal: messagesTotal, 1525 }) 1526 wg.Done() 1527 }() 1528 } 1529 return true 1530 }) 1531 wg.Wait() 1532 1533 n.runListeners(func(listener NotifyListener) { 1534 listener.ChatArchiveProgress(jobID, messagesComplete, messagesTotal) 1535 }) 1536 n.G().Log.CDebugf(ctx, "- Sent ChatArchiveProgress notification") 1537 } 1538 1539 func (n *NotifyRouter) HandleChatArchiveComplete(ctx context.Context, jobID chat1.ArchiveJobID) { 1540 if n == nil { 1541 return 1542 } 1543 var wg sync.WaitGroup 1544 n.G().Log.CDebugf(ctx, "+ Sending ChatArchiveComplete notification") 1545 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1546 if n.getNotificationChannels(id).Chatarchive { 1547 wg.Add(1) 1548 go func() { 1549 _ = (chat1.NotifyChatClient{ 1550 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1551 }).ChatArchiveComplete(context.Background(), 1552 jobID, 1553 ) 1554 wg.Done() 1555 }() 1556 } 1557 return true 1558 }) 1559 wg.Wait() 1560 1561 n.runListeners(func(listener NotifyListener) { 1562 listener.ChatArchiveComplete(jobID) 1563 }) 1564 n.G().Log.CDebugf(ctx, "- Sent ChatArchiveComplete notification") 1565 } 1566 1567 func (n *NotifyRouter) HandleChatSetConvRetention(ctx context.Context, uid keybase1.UID, 1568 convID chat1.ConversationID, topicType chat1.TopicType, conv *chat1.InboxUIItem) { 1569 n.notifyChatCommon(ctx, "ChatSetConvRetention", topicType, 1570 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1571 _ = cli.ChatSetConvRetention(ctx, chat1.ChatSetConvRetentionArg{ 1572 Uid: uid, 1573 ConvID: convID, 1574 Conv: conv, 1575 }) 1576 }, func(ctx context.Context, listener NotifyListener) { 1577 listener.ChatSetConvRetention(uid, convID) 1578 }) 1579 } 1580 1581 func (n *NotifyRouter) HandleChatSetTeamRetention(ctx context.Context, uid keybase1.UID, 1582 teamID keybase1.TeamID, topicType chat1.TopicType, convs []chat1.InboxUIItem) { 1583 n.notifyChatCommon(ctx, "ChatSetTeamRetention", topicType, 1584 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1585 _ = cli.ChatSetTeamRetention(ctx, chat1.ChatSetTeamRetentionArg{ 1586 Uid: uid, 1587 TeamID: teamID, 1588 Convs: convs, 1589 }) 1590 }, func(ctx context.Context, listener NotifyListener) { 1591 listener.ChatSetTeamRetention(uid, teamID) 1592 }) 1593 } 1594 1595 func (n *NotifyRouter) HandleChatSetConvSettings(ctx context.Context, uid keybase1.UID, 1596 convID chat1.ConversationID, topicType chat1.TopicType, conv *chat1.InboxUIItem) { 1597 n.notifyChatCommon(ctx, "ChatSetConvSettings", topicType, 1598 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1599 _ = cli.ChatSetConvSettings(ctx, chat1.ChatSetConvSettingsArg{ 1600 Uid: uid, 1601 ConvID: convID, 1602 Conv: conv, 1603 }) 1604 }, func(ctx context.Context, listener NotifyListener) { 1605 listener.ChatSetConvSettings(uid, convID) 1606 }) 1607 } 1608 1609 func (n *NotifyRouter) HandleChatSubteamRename(ctx context.Context, uid keybase1.UID, 1610 convIDs []chat1.ConversationID, topicType chat1.TopicType, convs []chat1.InboxUIItem) { 1611 n.notifyChatCommon(ctx, "ChatSubteamRename", topicType, 1612 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1613 _ = cli.ChatSubteamRename(ctx, chat1.ChatSubteamRenameArg{ 1614 Uid: uid, 1615 Convs: convs, 1616 }) 1617 }, func(ctx context.Context, listener NotifyListener) { 1618 listener.ChatSubteamRename(uid, convIDs) 1619 }) 1620 } 1621 1622 func (n *NotifyRouter) HandleChatPromptUnfurl(ctx context.Context, uid keybase1.UID, 1623 convID chat1.ConversationID, msgID chat1.MessageID, domain string) { 1624 n.notifyChatCommon(ctx, "ChatPromptUnfurl", chat1.TopicType_CHAT, 1625 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1626 _ = cli.ChatPromptUnfurl(ctx, chat1.ChatPromptUnfurlArg{ 1627 Uid: uid, 1628 ConvID: convID, 1629 MsgID: msgID, 1630 Domain: domain, 1631 }) 1632 }, func(ctx context.Context, listener NotifyListener) { 1633 listener.ChatPromptUnfurl(uid, convID, msgID, domain) 1634 }) 1635 } 1636 1637 func (n *NotifyRouter) HandleChatConvUpdate(ctx context.Context, uid keybase1.UID, 1638 convID chat1.ConversationID, topicType chat1.TopicType, conv *chat1.InboxUIItem) { 1639 n.notifyChatCommon(ctx, "ChatConvUpdate", topicType, 1640 func(ctx context.Context, cli *chat1.NotifyChatClient) { 1641 _ = cli.ChatConvUpdate(ctx, chat1.ChatConvUpdateArg{ 1642 Uid: uid, 1643 ConvID: convID, 1644 Conv: conv, 1645 }) 1646 }, func(ctx context.Context, listener NotifyListener) { 1647 listener.ChatConvUpdate(uid, convID) 1648 }) 1649 } 1650 1651 func (n *NotifyRouter) HandleChatWelcomeMessageLoaded(ctx context.Context, 1652 teamID keybase1.TeamID, message chat1.WelcomeMessageDisplay) { 1653 if n == nil { 1654 return 1655 } 1656 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1657 if n.getNotificationChannels(id).Chat { 1658 go func() { 1659 _ = (chat1.NotifyChatClient{ 1660 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1661 }).ChatWelcomeMessageLoaded(ctx, chat1.ChatWelcomeMessageLoadedArg{ 1662 TeamID: teamID, 1663 Message: message, 1664 }) 1665 }() 1666 } 1667 return true 1668 }) 1669 1670 n.runListeners(func(listener NotifyListener) { 1671 listener.ChatWelcomeMessageLoaded(teamID, message) 1672 }) 1673 } 1674 1675 func (n *NotifyRouter) HandleChatParticipantsInfo(ctx context.Context, 1676 participants map[chat1.ConvIDStr][]chat1.UIParticipant) { 1677 if n == nil { 1678 return 1679 } 1680 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1681 if n.getNotificationChannels(id).Chat { 1682 go func() { 1683 _ = (chat1.NotifyChatClient{ 1684 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1685 }).ChatParticipantsInfo(ctx, participants) 1686 }() 1687 } 1688 return true 1689 }) 1690 1691 n.runListeners(func(listener NotifyListener) { 1692 listener.ChatParticipantsInfo(participants) 1693 }) 1694 } 1695 1696 type notifyChatFn1 func(context.Context, *chat1.NotifyChatClient) 1697 type notifyChatFn2 func(context.Context, NotifyListener) 1698 1699 func (n *NotifyRouter) notifyChatCommon(ctx context.Context, debugLabel string, topicType chat1.TopicType, 1700 fn1 notifyChatFn1, fn2 notifyChatFn2) { 1701 if n == nil { 1702 return 1703 } 1704 var wg sync.WaitGroup 1705 n.G().Log.CDebugf(ctx, "+ Sending %v notification", debugLabel) 1706 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1707 if n.shouldSendChatNotification(id, topicType) { 1708 wg.Add(1) 1709 go func() { 1710 cli := &chat1.NotifyChatClient{ 1711 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1712 } 1713 fn1(context.Background(), cli) 1714 wg.Done() 1715 }() 1716 } 1717 return true 1718 }) 1719 wg.Wait() 1720 1721 n.runListeners(func(listener NotifyListener) { 1722 fn2(ctx, listener) 1723 }) 1724 n.G().Log.CDebugf(ctx, "- Sent %v notification", debugLabel) 1725 } 1726 1727 func (n *NotifyRouter) HandleWalletPaymentNotification(ctx context.Context, accountID stellar1.AccountID, paymentID stellar1.PaymentID) { 1728 if n == nil { 1729 return 1730 } 1731 n.G().Log.CDebugf(ctx, "+ Sending wallet PaymentNotification") 1732 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1733 // If the connection wants the `Wallet` notification type 1734 if n.getNotificationChannels(id).Wallet { 1735 // In the background do... 1736 go func() { 1737 arg := stellar1.PaymentNotificationArg{ 1738 AccountID: accountID, 1739 PaymentID: paymentID, 1740 } 1741 _ = (stellar1.NotifyClient{ 1742 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1743 }).PaymentNotification(context.Background(), arg) 1744 }() 1745 } 1746 return true 1747 }) 1748 1749 n.runListeners(func(listener NotifyListener) { 1750 listener.WalletPaymentNotification(accountID, paymentID) 1751 }) 1752 n.G().Log.CDebugf(ctx, "- Sent wallet PaymentNotification") 1753 } 1754 1755 func (n *NotifyRouter) HandleWalletPaymentStatusNotification(ctx context.Context, accountID stellar1.AccountID, paymentID stellar1.PaymentID) { 1756 if n == nil { 1757 return 1758 } 1759 n.G().Log.CDebugf(ctx, "+ Sending wallet PaymentStatusNotification") 1760 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1761 // If the connection wants the `Wallet` notification type 1762 if n.getNotificationChannels(id).Wallet { 1763 // In the background do... 1764 go func() { 1765 arg := stellar1.PaymentStatusNotificationArg{ 1766 AccountID: accountID, 1767 PaymentID: paymentID, 1768 } 1769 _ = (stellar1.NotifyClient{ 1770 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1771 }).PaymentStatusNotification(context.Background(), arg) 1772 }() 1773 } 1774 return true 1775 }) 1776 1777 n.runListeners(func(listener NotifyListener) { 1778 listener.WalletPaymentStatusNotification(accountID, paymentID) 1779 }) 1780 n.G().Log.CDebugf(ctx, "- Sent wallet PaymentStatusNotification") 1781 } 1782 1783 func (n *NotifyRouter) HandleWalletRequestStatusNotification(ctx context.Context, reqID stellar1.KeybaseRequestID) { 1784 if n == nil { 1785 return 1786 } 1787 n.G().Log.CDebugf(ctx, "+ Sending wallet RequestStatusNotification") 1788 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1789 // If the connection wants the `Wallet` notification type 1790 if n.getNotificationChannels(id).Wallet { 1791 // In the background do... 1792 go func() { 1793 _ = (stellar1.NotifyClient{ 1794 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1795 }).RequestStatusNotification(context.Background(), reqID) 1796 }() 1797 } 1798 return true 1799 }) 1800 1801 n.runListeners(func(listener NotifyListener) { 1802 listener.WalletRequestStatusNotification(reqID) 1803 }) 1804 n.G().Log.CDebugf(ctx, "- Sent wallet RequestStatusNotification") 1805 } 1806 1807 func (n *NotifyRouter) HandleWalletAccountDetailsUpdate(ctx context.Context, accountID stellar1.AccountID, account stellar1.WalletAccountLocal) { 1808 if n == nil { 1809 return 1810 } 1811 n.G().Log.CDebugf(ctx, "+ Sending wallet AccountDetailsUpdate") 1812 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1813 // If the connection wants the `Wallet` notification type 1814 if n.getNotificationChannels(id).Wallet { 1815 // In the background do... 1816 go func() { 1817 arg := stellar1.AccountDetailsUpdateArg{ 1818 AccountID: accountID, 1819 Account: account, 1820 } 1821 _ = (stellar1.NotifyClient{ 1822 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1823 }).AccountDetailsUpdate(context.Background(), arg) 1824 }() 1825 } 1826 return true 1827 }) 1828 1829 n.runListeners(func(listener NotifyListener) { 1830 listener.WalletAccountDetailsUpdate(accountID, account) 1831 }) 1832 n.G().Log.CDebugf(ctx, "- Sent wallet AccountDetailsUpdate") 1833 } 1834 1835 func (n *NotifyRouter) HandleWalletAccountsUpdate(ctx context.Context, accounts []stellar1.WalletAccountLocal) { 1836 if n == nil { 1837 return 1838 } 1839 n.G().Log.CDebugf(ctx, "+ Sending wallet AccountsUpdate") 1840 1841 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1842 // If the connection wants the `Wallet` notification type 1843 if n.getNotificationChannels(id).Wallet { 1844 // In the background do... 1845 go func() { 1846 _ = (stellar1.NotifyClient{ 1847 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1848 }).AccountsUpdate(context.Background(), accounts) 1849 }() 1850 } 1851 return true 1852 }) 1853 1854 n.runListeners(func(listener NotifyListener) { 1855 listener.WalletAccountsUpdate(accounts) 1856 }) 1857 n.G().Log.CDebugf(ctx, "- Sent wallet AccountsUpdate") 1858 } 1859 1860 func (n *NotifyRouter) HandleWalletPendingPaymentsUpdate(ctx context.Context, accountID stellar1.AccountID, pending []stellar1.PaymentOrErrorLocal) { 1861 if n == nil { 1862 return 1863 } 1864 n.G().Log.CDebugf(ctx, "+ Sending wallet PendingPaymentsUpdate") 1865 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1866 // If the connection wants the `Wallet` notification type 1867 if n.getNotificationChannels(id).Wallet { 1868 // In the background do... 1869 go func() { 1870 arg := stellar1.PendingPaymentsUpdateArg{ 1871 AccountID: accountID, 1872 Pending: pending, 1873 } 1874 _ = (stellar1.NotifyClient{ 1875 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1876 }).PendingPaymentsUpdate(context.Background(), arg) 1877 }() 1878 } 1879 return true 1880 }) 1881 1882 n.runListeners(func(listener NotifyListener) { 1883 listener.WalletPendingPaymentsUpdate(accountID, pending) 1884 }) 1885 n.G().Log.CDebugf(ctx, "- Sent wallet PendingPaymentsUpdate") 1886 } 1887 1888 func (n *NotifyRouter) HandleWalletRecentPaymentsUpdate(ctx context.Context, accountID stellar1.AccountID, firstPage stellar1.PaymentsPageLocal) { 1889 if n == nil { 1890 return 1891 } 1892 n.G().Log.CDebugf(ctx, "+ Sending wallet RecentPaymentsUpdate") 1893 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1894 // If the connection wants the `Wallet` notification type 1895 if n.getNotificationChannels(id).Wallet { 1896 // In the background do... 1897 go func() { 1898 arg := stellar1.RecentPaymentsUpdateArg{ 1899 AccountID: accountID, 1900 FirstPage: firstPage, 1901 } 1902 _ = (stellar1.NotifyClient{ 1903 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1904 }).RecentPaymentsUpdate(context.Background(), arg) 1905 }() 1906 } 1907 return true 1908 }) 1909 1910 n.runListeners(func(listener NotifyListener) { 1911 listener.WalletRecentPaymentsUpdate(accountID, firstPage) 1912 }) 1913 n.G().Log.CDebugf(ctx, "- Sent wallet RecentPaymentsUpdate") 1914 } 1915 1916 // HandlePaperKeyCached is called whenever a paper key is cached 1917 // in response to a rekey harassment. 1918 func (n *NotifyRouter) HandlePaperKeyCached(uid keybase1.UID, encKID keybase1.KID, sigKID keybase1.KID) { 1919 if n == nil { 1920 return 1921 } 1922 1923 n.G().Log.Debug("+ Sending paperkey cached notification") 1924 arg := keybase1.PaperKeyCachedArg{ 1925 Uid: uid, 1926 EncKID: encKID, 1927 SigKID: sigKID, 1928 } 1929 var wg sync.WaitGroup 1930 1931 // For all connections we currently have open... 1932 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1933 // If the connection wants the `Favorites` notification type 1934 if n.getNotificationChannels(id).Paperkeys { 1935 wg.Add(1) 1936 // In the background do... 1937 go func() { 1938 _ = (keybase1.NotifyPaperKeyClient{ 1939 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1940 }).PaperKeyCached(context.Background(), arg) 1941 wg.Done() 1942 }() 1943 } 1944 return true 1945 }) 1946 wg.Wait() 1947 1948 n.runListeners(func(listener NotifyListener) { 1949 listener.PaperKeyCached(uid, encKID, sigKID) 1950 }) 1951 n.G().Log.Debug("- Sent paperkey cached notification") 1952 } 1953 1954 // HandleKeyfamilyChanged is called whenever a user's keyfamily changes. 1955 func (n *NotifyRouter) HandleKeyfamilyChanged(uid keybase1.UID) { 1956 if n == nil { 1957 return 1958 } 1959 1960 n.G().Log.Debug("+ Sending keyfamily changed notification") 1961 // For all connections we currently have open... 1962 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1963 // If the connection wants the `Favorites` notification type 1964 if n.getNotificationChannels(id).Keyfamily { 1965 // In the background do... 1966 go func() { 1967 _ = (keybase1.NotifyKeyfamilyClient{ 1968 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 1969 }).KeyfamilyChanged(context.Background(), uid) 1970 }() 1971 } 1972 return true 1973 }) 1974 1975 n.runListeners(func(listener NotifyListener) { 1976 listener.KeyfamilyChanged(uid) 1977 }) 1978 n.G().Log.Debug("- Sent keyfamily changed notification") 1979 } 1980 1981 // HandleServiceShutdown is called whenever the service shuts down. 1982 func (n *NotifyRouter) HandleServiceShutdown() { 1983 if n == nil { 1984 return 1985 } 1986 1987 n.G().Log.Debug("+ Sending service shutdown notification") 1988 1989 var wg sync.WaitGroup 1990 1991 // For all connections we currently have open... 1992 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 1993 // If the connection wants the `Service` notification type 1994 if n.getNotificationChannels(id).Service { 1995 // In the background do... 1996 wg.Add(1) 1997 go func() { 1998 _ = (keybase1.NotifyServiceClient{ 1999 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2000 }).Shutdown(context.Background(), int(n.G().ExitCode)) 2001 wg.Done() 2002 }() 2003 } 2004 return true 2005 }) 2006 2007 done := make(chan struct{}) 2008 go func() { 2009 wg.Wait() 2010 close(done) 2011 }() 2012 2013 // timeout after 4s (launchd will SIGKILL after 5s) 2014 select { 2015 case <-done: 2016 n.G().Log.Debug("Finished sending service shutdown notifications") 2017 case <-time.After(4 * time.Second): 2018 n.G().Log.Warning("Timed out sending service shutdown notifications, proceeding to shutdown") 2019 } 2020 2021 n.G().Log.Debug("- Sent service shutdown notification") 2022 } 2023 2024 // HandleAppExit is called whenever an app exit command is issued 2025 func (n *NotifyRouter) HandleAppExit() { 2026 if n == nil { 2027 return 2028 } 2029 n.G().Log.Debug("+ Sending app exit notification") 2030 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2031 if n.getNotificationChannels(id).App { 2032 go func() { 2033 _ = (keybase1.NotifyAppClient{ 2034 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2035 }).Exit(context.Background()) 2036 }() 2037 } 2038 return true 2039 }) 2040 n.G().Log.Debug("- Sent app exit notification") 2041 } 2042 2043 // HandlePGPKeyInSecretStoreFile is called to notify a user that they have a PGP 2044 // key that is unlockable by a secret stored in a file in their home directory. 2045 func (n *NotifyRouter) HandlePGPKeyInSecretStoreFile() { 2046 n.G().Log.Debug("+ Sending pgpKeyInSecretStoreFile notification") 2047 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2048 if n.getNotificationChannels(id).PGP { 2049 go func() { 2050 _ = (keybase1.NotifyPGPClient{ 2051 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2052 }).PGPKeyInSecretStoreFile(context.Background()) 2053 }() 2054 } 2055 return true 2056 }) 2057 2058 n.runListeners(func(listener NotifyListener) { 2059 listener.PGPKeyInSecretStoreFile() 2060 }) 2061 n.G().Log.Debug("- Sent pgpKeyInSecretStoreFile notification") 2062 } 2063 2064 func (n *NotifyRouter) HandleReachability(r keybase1.Reachability) { 2065 n.G().Log.Debug("+ Sending reachability") 2066 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2067 if n.getNotificationChannels(id).Reachability { 2068 go func() { 2069 _ = (keybase1.ReachabilityClient{ 2070 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2071 }).ReachabilityChanged(context.Background(), r) 2072 }() 2073 } 2074 return true 2075 }) 2076 n.runListeners(func(listener NotifyListener) { 2077 listener.Reachability(r) 2078 }) 2079 n.G().Log.Debug("- Sent reachability") 2080 } 2081 2082 // teamID and teamName are not necessarily the same team 2083 func (n *NotifyRouter) HandleTeamChangedByBothKeys(ctx context.Context, 2084 teamID keybase1.TeamID, teamName string, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, 2085 latestHiddenSeqno keybase1.Seqno, latestOffchainSeqno keybase1.Seqno, source keybase1.TeamChangedSource) { 2086 2087 n.HandleTeamChangedByID(ctx, teamID, latestSeqno, implicitTeam, changes, latestHiddenSeqno, latestOffchainSeqno, source) 2088 n.HandleTeamChangedByName(ctx, teamName, latestSeqno, implicitTeam, changes, latestHiddenSeqno, latestOffchainSeqno, source) 2089 } 2090 2091 func (n *NotifyRouter) HandleTeamChangedByID(ctx context.Context, 2092 teamID keybase1.TeamID, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, 2093 latestHiddenSeqno keybase1.Seqno, latestOffchainSeqno keybase1.Seqno, source keybase1.TeamChangedSource) { 2094 2095 if n == nil { 2096 return 2097 } 2098 2099 arg := keybase1.TeamChangedByIDArg{ 2100 TeamID: teamID, 2101 LatestSeqno: latestSeqno, 2102 ImplicitTeam: implicitTeam, 2103 Changes: changes, 2104 LatestHiddenSeqno: latestHiddenSeqno, 2105 LatestOffchainSeqno: latestOffchainSeqno, 2106 Source: source, 2107 } 2108 2109 var wg sync.WaitGroup 2110 n.G().Log.CDebugf(ctx, "+ Sending TeamChangedByID notification (team:%v, seqno:%v, implicit:%v)", 2111 teamID, latestSeqno, implicitTeam) 2112 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2113 if n.getNotificationChannels(id).Team { 2114 wg.Add(1) 2115 go func() { 2116 _ = (keybase1.NotifyTeamClient{ 2117 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2118 }).TeamChangedByID(context.Background(), arg) 2119 wg.Done() 2120 }() 2121 } 2122 return true 2123 }) 2124 wg.Wait() 2125 2126 n.runListeners(func(listener NotifyListener) { 2127 listener.TeamChangedByID(teamID, latestSeqno, implicitTeam, changes, latestHiddenSeqno, source) 2128 }) 2129 n.G().Log.CDebugf(ctx, "- Sent TeamChangedByID notification") 2130 } 2131 2132 func (n *NotifyRouter) HandleTeamChangedByName(ctx context.Context, 2133 teamName string, latestSeqno keybase1.Seqno, implicitTeam bool, changes keybase1.TeamChangeSet, 2134 latestHiddenSeqno keybase1.Seqno, latestOffchainSeqno keybase1.Seqno, source keybase1.TeamChangedSource) { 2135 2136 if n == nil { 2137 return 2138 } 2139 2140 arg := keybase1.TeamChangedByNameArg{ 2141 TeamName: teamName, 2142 LatestSeqno: latestSeqno, 2143 ImplicitTeam: implicitTeam, 2144 Changes: changes, 2145 LatestHiddenSeqno: latestHiddenSeqno, 2146 LatestOffchainSeqno: latestOffchainSeqno, 2147 Source: source, 2148 } 2149 2150 var wg sync.WaitGroup 2151 n.G().Log.CDebugf(ctx, "+ Sending TeamChangedByName notification (team:%v, seqno:%v, implicit:%v)", 2152 teamName, latestSeqno, implicitTeam) 2153 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2154 if n.getNotificationChannels(id).Team { 2155 wg.Add(1) 2156 go func() { 2157 _ = (keybase1.NotifyTeamClient{ 2158 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2159 }).TeamChangedByName(context.Background(), arg) 2160 wg.Done() 2161 }() 2162 } 2163 return true 2164 }) 2165 wg.Wait() 2166 2167 n.runListeners(func(listener NotifyListener) { 2168 listener.TeamChangedByName(teamName, latestSeqno, implicitTeam, changes, latestHiddenSeqno, source) 2169 }) 2170 n.G().Log.CDebugf(ctx, "- Sent TeamChanged notification") 2171 } 2172 2173 // TeamMetadataUpdateUnverified is called when a notification is received that 2174 // affects the teams tab root page. 2175 func (n *NotifyRouter) HandleTeamMetadataUpdate(ctx context.Context) { 2176 if n == nil { 2177 return 2178 } 2179 2180 n.G().Log.Debug("+ Sending TeamMetadataUpdate notification") 2181 // For all connections we currently have open... 2182 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2183 // If the connection wants the `Team` notifications 2184 if n.getNotificationChannels(id).Team { 2185 // In the background do... 2186 go func() { 2187 // A send of a `TeamListUnverifiedChanged` RPC 2188 _ = (keybase1.NotifyTeamClient{ 2189 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2190 }).TeamMetadataUpdate(context.Background()) 2191 }() 2192 } 2193 return true 2194 }) 2195 2196 n.runListeners(func(listener NotifyListener) { 2197 listener.TeamMetadataUpdate() 2198 }) 2199 n.G().Log.Debug("- Sent TeamMetadata notification") 2200 } 2201 2202 // HandleCanUserPerformChanged is called when a notification is received from gregor that 2203 // we think might be of interest to the UI, specifically the parts of the UI that update 2204 // permissions for a user in a team. 2205 func (n *NotifyRouter) HandleCanUserPerformChanged(ctx context.Context, teamName string) { 2206 if n == nil { 2207 return 2208 } 2209 2210 n.G().Log.Debug("+ Sending CanUserPerformChanged notification (team:%v)", teamName) 2211 // For all connections we currently have open... 2212 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2213 // If the connection wants the `Team` notification type 2214 if n.getNotificationChannels(id).Team { 2215 // In the background do... 2216 go func() { 2217 // A send of a `CanUserPerformChanged` RPC 2218 _ = (keybase1.NotifyCanUserPerformClient{ 2219 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2220 }).CanUserPerformChanged(context.Background(), teamName) 2221 }() 2222 } 2223 return true 2224 }) 2225 2226 n.runListeners(func(listener NotifyListener) { 2227 listener.CanUserPerformChanged(teamName) 2228 }) 2229 n.G().Log.Debug("- Sent CanUserPerformChanged notification (team:%v)", teamName) 2230 } 2231 2232 func (n *NotifyRouter) HandleTeamDeleted(ctx context.Context, teamID keybase1.TeamID) { 2233 if n == nil { 2234 return 2235 } 2236 2237 var wg sync.WaitGroup 2238 n.G().Log.CDebugf(ctx, "+ Sending TeamDeleted notification") 2239 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2240 if n.getNotificationChannels(id).Team { 2241 wg.Add(1) 2242 go func() { 2243 _ = (keybase1.NotifyTeamClient{ 2244 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2245 }).TeamDeleted(context.Background(), teamID) 2246 wg.Done() 2247 }() 2248 } 2249 return true 2250 }) 2251 wg.Wait() 2252 2253 n.runListeners(func(listener NotifyListener) { 2254 listener.TeamDeleted(teamID) 2255 }) 2256 n.G().Log.CDebugf(ctx, "- Sent TeamDeleted notification") 2257 } 2258 2259 func (n *NotifyRouter) HandleTeamExit(ctx context.Context, teamID keybase1.TeamID) { 2260 if n == nil { 2261 return 2262 } 2263 2264 var wg sync.WaitGroup 2265 n.G().Log.CDebugf(ctx, "+ Sending TeamExit notification") 2266 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2267 if n.getNotificationChannels(id).Team { 2268 wg.Add(1) 2269 go func() { 2270 _ = (keybase1.NotifyTeamClient{ 2271 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2272 }).TeamExit(context.Background(), teamID) 2273 wg.Done() 2274 }() 2275 } 2276 return true 2277 }) 2278 wg.Wait() 2279 2280 n.runListeners(func(listener NotifyListener) { 2281 listener.TeamExit(teamID) 2282 }) 2283 n.G().Log.CDebugf(ctx, "- Sent TeamExit notification") 2284 } 2285 2286 func (n *NotifyRouter) HandleTeamRoleMapChanged(ctx context.Context, version keybase1.UserTeamVersion) { 2287 if n == nil { 2288 return 2289 } 2290 2291 var wg sync.WaitGroup 2292 n.G().Log.CDebugf(ctx, "+ Sending TeamRoleMapChanged notification") 2293 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2294 if n.getNotificationChannels(id).Team { 2295 wg.Add(1) 2296 go func() { 2297 _ = (keybase1.NotifyTeamClient{ 2298 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2299 }).TeamRoleMapChanged(context.Background(), version) 2300 wg.Done() 2301 }() 2302 } 2303 return true 2304 }) 2305 wg.Wait() 2306 2307 n.runListeners(func(listener NotifyListener) { 2308 listener.TeamRoleMapChanged(version) 2309 }) 2310 n.G().Log.CDebugf(ctx, "- Sent TeamRoleMapChanged notification (version %d)", version) 2311 } 2312 2313 func (n *NotifyRouter) HandleUserBlocked(ctx context.Context, b keybase1.UserBlockedBody) { 2314 if n == nil { 2315 return 2316 } 2317 2318 summary := b.Summarize() 2319 2320 var wg sync.WaitGroup 2321 n.G().Log.CDebugf(ctx, "+ Sending UserBlocked notification: %+v", b) 2322 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2323 if n.getNotificationChannels(id).Tracking { 2324 wg.Add(1) 2325 go func() { 2326 _ = (keybase1.NotifyTrackingClient{ 2327 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2328 }).NotifyUserBlocked(context.Background(), summary) 2329 wg.Done() 2330 }() 2331 } 2332 return true 2333 }) 2334 wg.Wait() 2335 2336 n.runListeners(func(listener NotifyListener) { 2337 listener.UserBlocked(b) 2338 }) 2339 n.G().Log.CDebugf(ctx, "- Sent UserBlocked notification") 2340 } 2341 2342 func (n *NotifyRouter) HandleTeamAbandoned(ctx context.Context, teamID keybase1.TeamID) { 2343 if n == nil { 2344 return 2345 } 2346 2347 var wg sync.WaitGroup 2348 n.G().Log.CDebugf(ctx, "+ Sending TeamAbandoned notification") 2349 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2350 if n.getNotificationChannels(id).Team { 2351 wg.Add(1) 2352 go func() { 2353 _ = (keybase1.NotifyTeamClient{ 2354 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2355 }).TeamAbandoned(context.Background(), teamID) 2356 wg.Done() 2357 }() 2358 } 2359 return true 2360 }) 2361 wg.Wait() 2362 2363 n.runListeners(func(listener NotifyListener) { 2364 listener.TeamExit(teamID) 2365 }) 2366 n.G().Log.CDebugf(ctx, "- Sent TeamAbandoned notification") 2367 } 2368 2369 func (n *NotifyRouter) HandleNewlyAddedToTeam(ctx context.Context, teamID keybase1.TeamID) { 2370 if n == nil { 2371 return 2372 } 2373 2374 var wg sync.WaitGroup 2375 n.G().Log.CDebugf(ctx, "+ Sending NewlyAddedToTeam notification") 2376 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2377 if n.getNotificationChannels(id).Team { 2378 wg.Add(1) 2379 go func() { 2380 _ = (keybase1.NotifyTeamClient{ 2381 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2382 }).NewlyAddedToTeam(context.Background(), teamID) 2383 wg.Done() 2384 }() 2385 } 2386 return true 2387 }) 2388 wg.Wait() 2389 2390 n.runListeners(func(listener NotifyListener) { 2391 listener.NewlyAddedToTeam(teamID) 2392 }) 2393 n.G().Log.CDebugf(ctx, "- Sent NewlyAddedToTeam notification") 2394 } 2395 2396 func (n *NotifyRouter) HandleNewTeamEK(ctx context.Context, teamID keybase1.TeamID, 2397 generation keybase1.EkGeneration) { 2398 if n == nil { 2399 return 2400 } 2401 2402 arg := keybase1.NewTeamEkArg{ 2403 Id: teamID, 2404 Generation: generation, 2405 } 2406 2407 var wg sync.WaitGroup 2408 n.G().Log.CDebugf(ctx, "+ Sending NewTeamEK notification") 2409 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2410 if n.getNotificationChannels(id).Ephemeral { 2411 wg.Add(1) 2412 go func() { 2413 _ = (keybase1.NotifyEphemeralClient{ 2414 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2415 }).NewTeamEk(context.Background(), arg) 2416 wg.Done() 2417 }() 2418 } 2419 return true 2420 }) 2421 wg.Wait() 2422 2423 n.runListeners(func(listener NotifyListener) { 2424 listener.NewTeamEK(teamID, generation) 2425 }) 2426 n.G().Log.CDebugf(ctx, "- Sent NewTeamEK notification") 2427 } 2428 2429 func (n *NotifyRouter) HandleNewTeambotEK(ctx context.Context, teamID keybase1.TeamID, 2430 generation keybase1.EkGeneration) { 2431 if n == nil { 2432 return 2433 } 2434 2435 arg := keybase1.NewTeambotEkArg{ 2436 Id: teamID, 2437 Generation: generation, 2438 } 2439 2440 var wg sync.WaitGroup 2441 n.G().Log.CDebugf(ctx, "+ Sending NewTeambotEK notification") 2442 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2443 if n.getNotificationChannels(id).Ephemeral { 2444 wg.Add(1) 2445 go func() { 2446 _ = (keybase1.NotifyEphemeralClient{ 2447 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2448 }).NewTeambotEk(context.Background(), arg) 2449 wg.Done() 2450 }() 2451 } 2452 return true 2453 }) 2454 wg.Wait() 2455 2456 n.runListeners(func(listener NotifyListener) { 2457 listener.NewTeambotEK(teamID, generation) 2458 }) 2459 n.G().Log.CDebugf(ctx, "- Sent NewTeambotEK notification") 2460 } 2461 2462 func (n *NotifyRouter) HandleTeambotEKNeeded(ctx context.Context, teamID keybase1.TeamID, 2463 botUID keybase1.UID, generation keybase1.EkGeneration, forceCreateGen *keybase1.EkGeneration) { 2464 if n == nil { 2465 return 2466 } 2467 2468 arg := keybase1.TeambotEkNeededArg{ 2469 Id: teamID, 2470 Uid: botUID, 2471 Generation: generation, 2472 ForceCreateGeneration: forceCreateGen, 2473 } 2474 2475 var wg sync.WaitGroup 2476 n.G().Log.CDebugf(ctx, "+ Sending TeambotEKNeeded notification") 2477 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2478 if n.getNotificationChannels(id).Ephemeral { 2479 wg.Add(1) 2480 go func() { 2481 _ = (keybase1.NotifyEphemeralClient{ 2482 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2483 }).TeambotEkNeeded(context.Background(), arg) 2484 wg.Done() 2485 }() 2486 } 2487 return true 2488 }) 2489 wg.Wait() 2490 2491 n.runListeners(func(listener NotifyListener) { 2492 listener.TeambotEKNeeded(teamID, botUID, generation, forceCreateGen) 2493 }) 2494 n.G().Log.CDebugf(ctx, "- Sent TeambotEKNeeded notification") 2495 } 2496 2497 func (n *NotifyRouter) HandleNewTeambotKey(ctx context.Context, teamID keybase1.TeamID, 2498 app keybase1.TeamApplication, generation keybase1.TeambotKeyGeneration) { 2499 if n == nil { 2500 return 2501 } 2502 2503 arg := keybase1.NewTeambotKeyArg{ 2504 Id: teamID, 2505 Application: app, 2506 Generation: generation, 2507 } 2508 2509 var wg sync.WaitGroup 2510 n.G().Log.CDebugf(ctx, "+ Sending NewTeambotKey notification") 2511 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2512 if n.getNotificationChannels(id).Teambot { 2513 wg.Add(1) 2514 go func() { 2515 _ = (keybase1.NotifyTeambotClient{ 2516 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2517 }).NewTeambotKey(context.Background(), arg) 2518 wg.Done() 2519 }() 2520 } 2521 return true 2522 }) 2523 wg.Wait() 2524 2525 n.runListeners(func(listener NotifyListener) { 2526 listener.NewTeambotKey(teamID, generation) 2527 }) 2528 n.G().Log.CDebugf(ctx, "- Sent NewTeambotKey notification") 2529 } 2530 2531 func (n *NotifyRouter) HandleTeambotKeyNeeded(ctx context.Context, teamID keybase1.TeamID, 2532 botUID keybase1.UID, app keybase1.TeamApplication, generation keybase1.TeambotKeyGeneration) { 2533 if n == nil { 2534 return 2535 } 2536 2537 arg := keybase1.TeambotKeyNeededArg{ 2538 Id: teamID, 2539 Application: app, 2540 Uid: botUID, 2541 Generation: generation, 2542 } 2543 2544 var wg sync.WaitGroup 2545 n.G().Log.CDebugf(ctx, "+ Sending TeambotKeyNeeded notification") 2546 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2547 if n.getNotificationChannels(id).Teambot { 2548 wg.Add(1) 2549 go func() { 2550 _ = (keybase1.NotifyTeambotClient{ 2551 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2552 }).TeambotKeyNeeded(context.Background(), arg) 2553 wg.Done() 2554 }() 2555 } 2556 return true 2557 }) 2558 wg.Wait() 2559 2560 n.runListeners(func(listener NotifyListener) { 2561 listener.TeambotKeyNeeded(teamID, botUID, generation) 2562 }) 2563 n.G().Log.CDebugf(ctx, "- Sent TeambotKeyNeeded notification") 2564 } 2565 2566 func (n *NotifyRouter) HandleAvatarUpdated(ctx context.Context, name string, formats []keybase1.AvatarFormat, 2567 typ keybase1.AvatarUpdateType) { 2568 if n == nil { 2569 return 2570 } 2571 arg := keybase1.AvatarUpdatedArg{ 2572 Name: name, 2573 Formats: formats, 2574 Typ: typ, 2575 } 2576 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2577 if n.getNotificationChannels(id).Team { 2578 go func() { 2579 _ = (keybase1.NotifyTeamClient{ 2580 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2581 }).AvatarUpdated(context.Background(), arg) 2582 }() 2583 } 2584 return true 2585 }) 2586 2587 n.runListeners(func(listener NotifyListener) { 2588 listener.AvatarUpdated(name, formats) 2589 }) 2590 } 2591 2592 func (n *NotifyRouter) HandlePhoneNumbersChanged(ctx context.Context, list []keybase1.UserPhoneNumber, category string, phoneNumber keybase1.PhoneNumber) { 2593 if n == nil { 2594 return 2595 } 2596 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2597 if n.getNotificationChannels(id).Team { 2598 go func() { 2599 _ = (keybase1.NotifyPhoneNumberClient{ 2600 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2601 }).PhoneNumbersChanged(context.Background(), keybase1.PhoneNumbersChangedArg{ 2602 List: list, 2603 Category: category, 2604 PhoneNumber: phoneNumber, 2605 }) 2606 }() 2607 } 2608 return true 2609 }) 2610 2611 n.runListeners(func(listener NotifyListener) { 2612 listener.PhoneNumbersChanged(list, category, phoneNumber) 2613 }) 2614 } 2615 2616 func (n *NotifyRouter) HandleEmailAddressVerified(ctx context.Context, emailAddress keybase1.EmailAddress) { 2617 if n == nil { 2618 return 2619 } 2620 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2621 if n.getNotificationChannels(id).Team { 2622 go func() { 2623 _ = (keybase1.NotifyEmailAddressClient{ 2624 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2625 }).EmailAddressVerified(context.Background(), emailAddress) 2626 }() 2627 } 2628 return true 2629 }) 2630 2631 n.runListeners(func(listener NotifyListener) { 2632 listener.EmailAddressVerified(emailAddress) 2633 }) 2634 } 2635 2636 func (n *NotifyRouter) HandleEmailAddressChanged(ctx context.Context, list []keybase1.Email, category string, emailAddress keybase1.EmailAddress) { 2637 if n == nil { 2638 return 2639 } 2640 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2641 if n.getNotificationChannels(id).Team { 2642 go func() { 2643 _ = (keybase1.NotifyEmailAddressClient{ 2644 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2645 }).EmailsChanged(context.Background(), keybase1.EmailsChangedArg{ 2646 List: list, 2647 Category: category, 2648 Email: emailAddress, 2649 }) 2650 }() 2651 } 2652 return true 2653 }) 2654 2655 n.runListeners(func(listener NotifyListener) { 2656 listener.EmailsChanged(list, category, emailAddress) 2657 }) 2658 } 2659 2660 func (n *NotifyRouter) HandleChatPaymentInfo(ctx context.Context, uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, info chat1.UIPaymentInfo) { 2661 if n == nil { 2662 return 2663 } 2664 var wg sync.WaitGroup 2665 n.G().Log.CDebugf(ctx, "+ Sending ChatPaymentInfo notification") 2666 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2667 if n.shouldSendChatNotification(id, chat1.TopicType_NONE) { 2668 wg.Add(1) 2669 go func() { 2670 _ = (chat1.NotifyChatClient{ 2671 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2672 }).ChatPaymentInfo(context.Background(), chat1.ChatPaymentInfoArg{ 2673 Uid: uid, 2674 ConvID: convID, 2675 MsgID: msgID, 2676 Info: info, 2677 }) 2678 wg.Done() 2679 }() 2680 } 2681 return true 2682 }) 2683 wg.Wait() 2684 2685 n.runListeners(func(listener NotifyListener) { 2686 listener.ChatPaymentInfo(uid, convID, msgID, info) 2687 }) 2688 n.G().Log.CDebugf(ctx, "- Sent ChatPaymentInfo notification") 2689 } 2690 2691 func (n *NotifyRouter) HandleChatRequestInfo(ctx context.Context, uid keybase1.UID, convID chat1.ConversationID, msgID chat1.MessageID, info chat1.UIRequestInfo) { 2692 if n == nil { 2693 return 2694 } 2695 var wg sync.WaitGroup 2696 n.G().Log.CDebugf(ctx, "+ Sending ChatRequestInfo notification") 2697 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2698 if n.shouldSendChatNotification(id, chat1.TopicType_NONE) { 2699 wg.Add(1) 2700 go func() { 2701 _ = (chat1.NotifyChatClient{ 2702 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2703 }).ChatRequestInfo(context.Background(), chat1.ChatRequestInfoArg{ 2704 Uid: uid, 2705 ConvID: convID, 2706 MsgID: msgID, 2707 Info: info, 2708 }) 2709 wg.Done() 2710 }() 2711 } 2712 return true 2713 }) 2714 wg.Wait() 2715 2716 n.runListeners(func(listener NotifyListener) { 2717 listener.ChatRequestInfo(uid, convID, msgID, info) 2718 }) 2719 n.G().Log.CDebugf(ctx, "- Sent ChatRequestInfo notification") 2720 } 2721 2722 func (n *NotifyRouter) HandlePasswordChanged(ctx context.Context, passphraseState keybase1.PassphraseState) { 2723 if n == nil { 2724 return 2725 } 2726 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2727 if n.getNotificationChannels(id).Users { 2728 go func() { 2729 _ = (keybase1.NotifyUsersClient{ 2730 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2731 }).PasswordChanged(context.Background(), passphraseState) 2732 }() 2733 } 2734 return true 2735 }) 2736 2737 n.runListeners(func(listener NotifyListener) { 2738 listener.PasswordChanged() 2739 }) 2740 } 2741 2742 // RootAuditError is called when the merkle root auditor finds an invalid skip 2743 // sequence in a random old block. 2744 func (n *NotifyRouter) HandleRootAuditError(msg string) { 2745 if n == nil { 2746 return 2747 } 2748 n.G().Log.Debug("+ Sending merkle tree audit notification") 2749 // For all connections we currently have open... 2750 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2751 // If the connection wants the `Session` notification type 2752 if n.getNotificationChannels(id).Audit { 2753 // In the background do... 2754 go func() { 2755 // A send of a `RootAuditError` RPC 2756 _ = (keybase1.NotifyAuditClient{ 2757 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2758 }).RootAuditError(context.Background(), msg) 2759 }() 2760 } 2761 return true 2762 }) 2763 2764 n.runListeners(func(listener NotifyListener) { 2765 listener.RootAuditError(msg) 2766 }) 2767 2768 n.G().Log.Debug("- merkle tree audit notification sent") 2769 } 2770 2771 func (n *NotifyRouter) HandleBoxAuditError(ctx context.Context, msg string) { 2772 if n == nil { 2773 return 2774 } 2775 n.G().Log.CDebugf(ctx, "+ Sending BoxAuditError notification") 2776 defer n.G().Log.CDebugf(ctx, "- Sending BoxAuditError notification") 2777 2778 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2779 if n.getNotificationChannels(id).Audit { 2780 go func() { 2781 _ = (keybase1.NotifyAuditClient{ 2782 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2783 }).BoxAuditError(context.Background(), msg) 2784 }() 2785 } 2786 return true 2787 }) 2788 2789 n.runListeners(func(listener NotifyListener) { 2790 listener.BoxAuditError(msg) 2791 }) 2792 } 2793 2794 func (n *NotifyRouter) HandleRuntimeStatsUpdate(ctx context.Context, stats *keybase1.RuntimeStats) { 2795 if n == nil { 2796 return 2797 } 2798 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2799 if n.getNotificationChannels(id).Runtimestats { 2800 go func() { 2801 _ = (keybase1.NotifyRuntimeStatsClient{ 2802 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2803 }).RuntimeStatsUpdate(ctx, stats) 2804 }() 2805 } 2806 return true 2807 }) 2808 n.runListeners(func(listener NotifyListener) { 2809 listener.RuntimeStatsUpdate(stats) 2810 }) 2811 } 2812 2813 func (n *NotifyRouter) HandleHTTPSrvInfoUpdate(ctx context.Context, info keybase1.HttpSrvInfo) { 2814 if n == nil { 2815 return 2816 } 2817 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2818 if n.getNotificationChannels(id).Service { 2819 go func() { 2820 _ = (keybase1.NotifyServiceClient{ 2821 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2822 }).HTTPSrvInfoUpdate(ctx, info) 2823 }() 2824 } 2825 return true 2826 }) 2827 n.runListeners(func(listener NotifyListener) { 2828 listener.HTTPSrvInfoUpdate(info) 2829 }) 2830 } 2831 2832 func (n *NotifyRouter) HandleHandleKeybaseLink(ctx context.Context, link string, deferred bool) { 2833 if n == nil { 2834 return 2835 } 2836 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2837 if n.getNotificationChannels(id).Service { 2838 go func() { 2839 _ = (keybase1.NotifyServiceClient{ 2840 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2841 }).HandleKeybaseLink(ctx, keybase1.HandleKeybaseLinkArg{ 2842 Link: link, 2843 Deferred: deferred, 2844 }) 2845 }() 2846 } 2847 return true 2848 }) 2849 n.runListeners(func(listener NotifyListener) { 2850 listener.HandleKeybaseLink(link, deferred) 2851 }) 2852 } 2853 2854 func (n *NotifyRouter) HandleIdentifyUpdate(ctx context.Context, okUsernames []string, brokenUsernames []string) { 2855 if n == nil { 2856 return 2857 } 2858 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2859 if n.getNotificationChannels(id).Users { 2860 go func() { 2861 _ = (keybase1.NotifyUsersClient{ 2862 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2863 }).IdentifyUpdate(ctx, keybase1.IdentifyUpdateArg{ 2864 OkUsernames: okUsernames, 2865 BrokenUsernames: brokenUsernames, 2866 }) 2867 }() 2868 } 2869 return true 2870 }) 2871 n.runListeners(func(listener NotifyListener) { 2872 listener.IdentifyUpdate(okUsernames, brokenUsernames) 2873 }) 2874 } 2875 2876 func (n *NotifyRouter) HandleFeaturedBots(ctx context.Context, bots []keybase1.FeaturedBot, limit, offset int) { 2877 if n == nil { 2878 return 2879 } 2880 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2881 if n.getNotificationChannels(id).FeaturedBots { 2882 go func() { 2883 _ = (keybase1.NotifyFeaturedBotsClient{ 2884 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2885 }).FeaturedBotsUpdate(ctx, keybase1.FeaturedBotsUpdateArg{ 2886 Bots: bots, 2887 Limit: limit, 2888 Offset: offset, 2889 }) 2890 }() 2891 } 2892 return true 2893 }) 2894 n.runListeners(func(listener NotifyListener) { 2895 listener.FeaturedBotsUpdate(bots, limit, offset) 2896 }) 2897 } 2898 2899 func (n *NotifyRouter) HandleSaltpackOperationStart(ctx context.Context, opType keybase1.SaltpackOperationType, filename string) { 2900 if n == nil { 2901 return 2902 } 2903 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2904 if n.getNotificationChannels(id).Saltpack { 2905 // note there's no goroutine here on purpose 2906 // (notification ordering) 2907 _ = (keybase1.NotifySaltpackClient{ 2908 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2909 }).SaltpackOperationStart(context.Background(), keybase1.SaltpackOperationStartArg{ 2910 OpType: opType, 2911 Filename: filename, 2912 }) 2913 } 2914 return true 2915 }) 2916 2917 n.runListeners(func(listener NotifyListener) { 2918 listener.SaltpackOperationStart(opType, filename) 2919 }) 2920 } 2921 2922 func (n *NotifyRouter) HandleSaltpackOperationProgress(ctx context.Context, opType keybase1.SaltpackOperationType, filename string, bytesComplete, bytesTotal int64) { 2923 if n == nil { 2924 return 2925 } 2926 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2927 if n.getNotificationChannels(id).Saltpack { 2928 // note there's no goroutine here on purpose 2929 // (notification ordering) 2930 _ = (keybase1.NotifySaltpackClient{ 2931 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2932 }).SaltpackOperationProgress(context.Background(), keybase1.SaltpackOperationProgressArg{ 2933 OpType: opType, 2934 Filename: filename, 2935 BytesComplete: bytesComplete, 2936 BytesTotal: bytesTotal, 2937 }) 2938 } 2939 return true 2940 }) 2941 2942 n.runListeners(func(listener NotifyListener) { 2943 listener.SaltpackOperationDone(opType, filename) 2944 }) 2945 } 2946 2947 func (n *NotifyRouter) HandleSaltpackOperationDone(ctx context.Context, opType keybase1.SaltpackOperationType, filename string) { 2948 if n == nil { 2949 return 2950 } 2951 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2952 if n.getNotificationChannels(id).Saltpack { 2953 // note there's no goroutine here on purpose 2954 // (notification ordering) 2955 _ = (keybase1.NotifySaltpackClient{ 2956 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2957 }).SaltpackOperationDone(context.Background(), keybase1.SaltpackOperationDoneArg{ 2958 OpType: opType, 2959 Filename: filename, 2960 }) 2961 } 2962 return true 2963 }) 2964 2965 n.runListeners(func(listener NotifyListener) { 2966 listener.SaltpackOperationDone(opType, filename) 2967 }) 2968 } 2969 2970 func (n *NotifyRouter) HandleUpdateInviteCounts(ctx context.Context, counts keybase1.InviteCounts) { 2971 if n == nil { 2972 return 2973 } 2974 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2975 if n.getNotificationChannels(id).App { 2976 go func() { 2977 _ = (keybase1.NotifyInviteFriendsClient{ 2978 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 2979 }).UpdateInviteCounts(context.Background(), counts) 2980 }() 2981 } 2982 return true 2983 }) 2984 2985 n.runListeners(func(listener NotifyListener) { 2986 listener.UpdateInviteCounts(counts) 2987 }) 2988 } 2989 2990 func (n *NotifyRouter) HandleTeamTreeMembershipsPartial(ctx context.Context, 2991 result keybase1.TeamTreeMembership) { 2992 2993 if n == nil { 2994 return 2995 } 2996 2997 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 2998 if n.getNotificationChannels(id).Team { 2999 go func() { 3000 _ = (keybase1.NotifyTeamClient{ 3001 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 3002 }).TeamTreeMembershipsPartial(context.Background(), result) 3003 }() 3004 } 3005 return true 3006 }) 3007 3008 n.runListeners(func(listener NotifyListener) { 3009 listener.TeamTreeMembershipsPartial(result) 3010 }) 3011 } 3012 3013 func (n *NotifyRouter) HandleTeamTreeMembershipsDone(ctx context.Context, result keybase1.TeamTreeMembershipsDoneResult) { 3014 if n == nil { 3015 return 3016 } 3017 3018 n.cm.ApplyAll(func(id ConnectionID, xp rpc.Transporter) bool { 3019 if n.getNotificationChannels(id).Team { 3020 go func() { 3021 _ = (keybase1.NotifyTeamClient{ 3022 Cli: rpc.NewClient(xp, NewContextifiedErrorUnwrapper(n.G()), nil), 3023 }).TeamTreeMembershipsDone(context.Background(), result) 3024 }() 3025 } 3026 return true 3027 }) 3028 3029 n.runListeners(func(listener NotifyListener) { 3030 listener.TeamTreeMembershipsDone(result) 3031 }) 3032 }