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  }