github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/favorite_add.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 engine 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/keybase/client/go/externals" 11 "github.com/keybase/client/go/libkb" 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 13 ) 14 15 // FavoriteAdd is an engine. 16 type FavoriteAdd struct { 17 arg *keybase1.FavoriteAddArg 18 checkInviteDone chan struct{} 19 libkb.Contextified 20 } 21 22 // NewFavoriteAdd creates a FavoriteAdd engine. 23 func NewFavoriteAdd(g *libkb.GlobalContext, arg *keybase1.FavoriteAddArg) *FavoriteAdd { 24 return &FavoriteAdd{ 25 arg: arg, 26 checkInviteDone: make(chan struct{}), 27 Contextified: libkb.NewContextified(g), 28 } 29 } 30 31 // Name is the unique engine name. 32 func (e *FavoriteAdd) Name() string { 33 return "FavoriteAdd" 34 } 35 36 // GetPrereqs returns the engine prereqs. 37 func (e *FavoriteAdd) Prereqs() Prereqs { 38 return Prereqs{ 39 Device: true, 40 } 41 } 42 43 // RequiredUIs returns the required UIs. 44 func (e *FavoriteAdd) RequiredUIs() []libkb.UIKind { 45 return []libkb.UIKind{ 46 libkb.IdentifyUIKind, 47 } 48 } 49 50 // SubConsumers returns the other UI consumers for this engine. 51 func (e *FavoriteAdd) SubConsumers() []libkb.UIConsumer { 52 return nil 53 } 54 55 func (e *FavoriteAdd) WantDelegate(kind libkb.UIKind) bool { 56 return kind == libkb.IdentifyUIKind 57 } 58 59 // Run starts the engine. 60 func (e *FavoriteAdd) Run(m libkb.MetaContext) error { 61 if e.arg == nil { 62 return fmt.Errorf("FavoriteAdd arg is nil") 63 } 64 _, err := m.G().API.Post(m, libkb.APIArg{ 65 Endpoint: "kbfs/favorite/add", 66 SessionType: libkb.APISessionTypeREQUIRED, 67 Args: libkb.HTTPArgs{ 68 "tlf_name": libkb.S{Val: e.arg.Folder.Name}, 69 "folder_type": libkb.I{Val: int(e.arg.Folder.FolderType)}, 70 "status": libkb.S{Val: "favorite"}, 71 }, 72 }) 73 if err != nil { 74 return err 75 } 76 77 // this should be in its own goroutine so that potential 78 // UI calls don't block FavoriteAdd calls 79 go func() { _ = e.checkInviteNeeded(m) }() 80 81 return nil 82 } 83 84 // Wait until the checkInviteNeeded goroutine is done. 85 func (e *FavoriteAdd) Wait() { 86 <-e.checkInviteDone 87 } 88 89 func (e *FavoriteAdd) checkInviteNeeded(m libkb.MetaContext) error { 90 defer func() { 91 close(e.checkInviteDone) 92 }() 93 94 // If not folder creator, do nothing. 95 if !e.arg.Folder.Created { 96 return nil 97 } 98 99 for _, user := range strings.Split(e.arg.Folder.Name, ",") { 100 assertion, ok := externals.NormalizeSocialAssertion(m, user) 101 if !ok { 102 m.Debug("not a social assertion: %s", user) 103 continue 104 } 105 106 m.Debug("social assertion found in FavoriteAdd folder name: %s", assertion) 107 m.Debug("requesting an invitation for %s", assertion) 108 109 inv, err := libkb.GenerateInvitationCodeForAssertion(m, assertion, libkb.InviteArg{}) 110 if err != nil { 111 return err 112 } 113 114 m.Debug("invitation requested, informing folder creator with result") 115 arg := keybase1.DisplayTLFCreateWithInviteArg{ 116 FolderName: e.arg.Folder.Name, 117 Assertion: assertion.String(), 118 SocialAssertion: assertion, 119 IsPrivate: e.arg.Folder.FolderType == keybase1.FolderType_PRIVATE, 120 Throttled: inv.Throttled, 121 InviteLink: inv.Link(), 122 } 123 if err := m.UIs().IdentifyUI.DisplayTLFCreateWithInvite(m, arg); err != nil { 124 return err 125 } 126 } 127 128 return nil 129 }