package client import ( "context" "fmt" "time" "forge.cadoles.com/arcad/arcast/pkg/client" "forge.cadoles.com/arcad/arcast/pkg/network" "github.com/pkg/errors" "github.com/urfave/cli/v2" ) var ( playerScanTimeoutFlag = "scan-timeout" flagPlayerAddr = "player-address" flagPlayerID = "player-id" playerFlags = []cli.Flag{ &cli.DurationFlag{ Name: playerScanTimeoutFlag, EnvVars: []string{"ARCAST_CLIENT_CAST_TIMEOUT"}, Usage: "Use `TIMEOUT` as maximum cast duration", Value: 5 * time.Second, }, &cli.StringSliceFlag{ Name: flagPlayerID, Aliases: []string{"i"}, EnvVars: []string{"ARCAST_CLIENT_PLAYER_ID"}, Usage: "Use `ID` as player id", Value: cli.NewStringSlice(), }, &cli.StringSliceFlag{ Name: flagPlayerAddr, Aliases: []string{"a"}, EnvVars: []string{"ARCAST_CLIENT_PLAYER_ADDR"}, Usage: "Use `ADDR` as player address", Value: cli.NewStringSlice(), }, } ) func forEachPlayer(ctx *cli.Context, fn func(cl *client.Client, playerAddr string) error) error { playerAddrs := ctx.StringSlice(flagPlayerAddr) cl := client.New() if ctx.IsSet(flagPlayerID) || !ctx.IsSet(flagPlayerAddr) { scanTimeout := ctx.Duration(playerScanTimeoutFlag) scanCtx, cancel := context.WithTimeout(ctx.Context, scanTimeout) defer cancel() playerIDs := ctx.StringSlice(flagPlayerID) players, err := cl.Scan(scanCtx, client.WithPlayerIDs(playerIDs...)) if err != nil && (!errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded)) { return errors.Wrap(err, "could not scan for players") } for _, p := range players { preferredIP, err := network.FindPreferredLocalAddress(p.IPs...) if err != nil { return errors.Errorf("could not retrieve player '%s' preferred address", p.ID) } playerAddr := fmt.Sprintf("%s:%d", preferredIP, p.Port) playerAddrs = append(playerAddrs, playerAddr) } } if len(playerAddrs) == 0 { return errors.New("no players found") } for _, addr := range playerAddrs { if err := fn(cl, addr); err != nil { return errors.WithStack(err) } } return nil } func AsAnySlice[T any](src ...T) []any { dst := make([]any, len(src)) for i, s := range src { dst[i] = s } return dst }