package client import ( "context" "encoding/json" "fmt" "log/slog" "git.franklin.lab/steve.cliff/pcli/model" ) func (c *Client) GetCard(ctx context.Context, id string) (*model.Card, error) { data, err := c.DoNoBody(ctx, "GET", fmt.Sprintf("/api/cards/%s", id)) if err != nil { return nil, err } var response struct { Item model.Card `json:"item"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal card response: %w", err) } return &response.Item, nil } func (c *Client) CreateCard(ctx context.Context, listId string, fields map[string]any) (*model.Card, error) { data, err := c.Do(ctx, "POST", fmt.Sprintf("/api/lists/%s/cards", listId), fields) if err != nil { return nil, err } var response struct { Item model.Card `json:"item"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal card response: %w", err) } return &response.Item, nil } func (c *Client) UpdateCard(ctx context.Context, id string, fields map[string]any) (*model.Card, error) { data, err := c.Do(ctx, "PATCH", fmt.Sprintf("/api/cards/%s", id), fields) if err != nil { return nil, err } var response struct { Item model.Card `json:"item"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal card response: %w", err) } return &response.Item, nil } func (c *Client) DeleteCard(ctx context.Context, id string) error { _, err := c.DoNoBody(ctx, "DELETE", fmt.Sprintf("/api/cards/%s", id)) return err } func (c *Client) DuplicateCard(ctx context.Context, id string, name *string, position *float64) (*model.Card, error) { fields := make(map[string]any) if name != nil { fields["name"] = *name } if position != nil { fields["position"] = *position } data, err := c.Do(ctx, "POST", fmt.Sprintf("/api/cards/%s/duplicate", id), fields) if err != nil { return nil, err } var response struct { Item model.Card `json:"item"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal card response: %w", err) } return &response.Item, nil } func (c *Client) ListCards(ctx context.Context, listId string, limit int) ([]model.Card, error) { var all []model.Card var before string for { path := fmt.Sprintf("/api/lists/%s/cards", listId) if before != "" { path = fmt.Sprintf("%s?before=%s", path, before) } c.Logger.Debug("Fetching cards page", slog.String("listId", listId), slog.String("before", before), ) data, err := c.DoNoBody(ctx, "GET", path) if err != nil { return nil, err } var response struct { Items []model.Card `json:"items"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal cards response: %w", err) } if len(response.Items) == 0 { break } all = append(all, response.Items...) if limit > 0 && len(all) >= limit { all = all[:limit] break } before = response.Items[len(response.Items)-1].ID } return all, nil } func (c *Client) ListCardActions(ctx context.Context, cardId string, limit int) ([]model.Action, error) { var all []model.Action var beforeId string for { path := fmt.Sprintf("/api/cards/%s/actions", cardId) if beforeId != "" { path = fmt.Sprintf("%s?beforeId=%s", path, beforeId) } c.Logger.Debug("Fetching card actions page", slog.String("cardId", cardId), slog.String("beforeId", beforeId), ) data, err := c.DoNoBody(ctx, "GET", path) if err != nil { return nil, err } var response struct { Items []model.Action `json:"items"` } if err := json.Unmarshal(data, &response); err != nil { return nil, fmt.Errorf("failed to unmarshal card actions response: %w", err) } if len(response.Items) == 0 { break } all = append(all, response.Items...) if limit > 0 && len(all) >= limit { all = all[:limit] break } beforeId = response.Items[len(response.Items)-1].ID } return all, nil } func (c *Client) ListCardsByBoard(ctx context.Context, boardId string, limit int) ([]model.CardWithList, error) { board, err := c.GetBoard(ctx, boardId) if err != nil { return nil, fmt.Errorf("failed to get board: %w", err) } listNames := make(map[string]string) for _, list := range board.Lists { name := "" if list.Name != nil { name = *list.Name } listNames[list.ID] = name } var allCards []model.CardWithList for _, card := range board.Cards { cardWithList := model.CardWithList{ Card: card, ListName: listNames[card.ListID], } allCards = append(allCards, cardWithList) if limit > 0 && len(allCards) >= limit { return allCards[:limit], nil } } return allCards, nil } func (c *Client) AddCardLabel(ctx context.Context, cardId, labelId string) error { fields := map[string]any{ "labelId": labelId, } _, err := c.DoWithFallback(ctx, "POST", fmt.Sprintf("/api/cards/%s/card-labels", cardId), fmt.Sprintf("/api/cards/%s/labels", cardId), fields) return err } func (c *Client) RemoveCardLabel(ctx context.Context, cardId, labelId string) error { _, err := c.DoNoBodyWithFallback(ctx, "DELETE", fmt.Sprintf("/api/cards/%s/card-labels/labelId:%s", cardId, labelId), fmt.Sprintf("/api/cards/%s/labels/%s", cardId, labelId)) return err } func (c *Client) AddCardMember(ctx context.Context, cardId, userId string) error { fields := map[string]any{ "userId": userId, } _, err := c.DoWithFallback(ctx, "POST", fmt.Sprintf("/api/cards/%s/card-memberships", cardId), fmt.Sprintf("/api/cards/%s/memberships", cardId), fields) return err } func (c *Client) RemoveCardMember(ctx context.Context, cardId, userId string) error { _, err := c.DoNoBodyWithFallback(ctx, "DELETE", fmt.Sprintf("/api/cards/%s/card-memberships/userId:%s", cardId, userId), fmt.Sprintf("/api/cards/%s/memberships/%s", cardId, userId)) return err }