1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package person
6
7import (
8 "fmt"
9 "os"
10 "strings"
11
12 "git.secluded.site/go-lunatask"
13 "git.secluded.site/lune/internal/client"
14 "git.secluded.site/lune/internal/dateutil"
15 "git.secluded.site/lune/internal/ui"
16 "git.secluded.site/lune/internal/validate"
17 "github.com/spf13/cobra"
18)
19
20// TimelineCmd adds a timeline note to a person. Exported for potential use by shortcuts.
21var TimelineCmd = &cobra.Command{
22 Use: "timeline ID",
23 Short: "Add a timeline note",
24 Long: `Add a timeline note to a person's memory timeline.
25
26Use "-" as content flag value to read from stdin.`,
27 Args: cobra.ExactArgs(1),
28 RunE: runTimeline,
29}
30
31func init() {
32 TimelineCmd.Flags().StringP("content", "c", "", "Note content (use - for stdin)")
33 TimelineCmd.Flags().StringP("date", "d", "", "Date of interaction (natural language)")
34}
35
36func runTimeline(cmd *cobra.Command, args []string) error {
37 personID, err := validate.Reference(args[0])
38 if err != nil {
39 return err
40 }
41
42 apiClient, err := client.New()
43 if err != nil {
44 return err
45 }
46
47 builder := apiClient.NewTimelineNote(personID)
48
49 if err := applyTimelineContent(cmd, builder); err != nil {
50 return err
51 }
52
53 if err := applyTimelineDate(cmd, builder); err != nil {
54 return err
55 }
56
57 note, err := builder.Create(cmd.Context())
58 if err != nil {
59 return err
60 }
61
62 fmt.Fprintln(cmd.OutOrStdout(), ui.Success.Render("Created timeline note: "+note.ID))
63
64 return nil
65}
66
67func applyTimelineContent(cmd *cobra.Command, builder *lunatask.TimelineNoteBuilder) error {
68 content, _ := cmd.Flags().GetString("content")
69 if content == "" {
70 return nil
71 }
72
73 resolved, err := resolveContent(content)
74 if err != nil {
75 return err
76 }
77
78 builder.WithContent(resolved)
79
80 return nil
81}
82
83func resolveContent(content string) (string, error) {
84 if content != "-" {
85 return content, nil
86 }
87
88 data, err := os.ReadFile("/dev/stdin")
89 if err != nil {
90 return "", fmt.Errorf("reading stdin: %w", err)
91 }
92
93 return strings.TrimSpace(string(data)), nil
94}
95
96func applyTimelineDate(cmd *cobra.Command, builder *lunatask.TimelineNoteBuilder) error {
97 dateStr, _ := cmd.Flags().GetString("date")
98 if dateStr == "" {
99 return nil
100 }
101
102 date, err := dateutil.Parse(dateStr)
103 if err != nil {
104 return err
105 }
106
107 builder.OnDate(date)
108
109 return nil
110}