Monorepo for Tangled
tangled.org
1package db
2
3import (
4 "context"
5 "fmt"
6 "time"
7
8 "tangled.org/core/appview/models"
9 "tangled.org/core/orm"
10)
11
12func UpsertRecentLink(e Execer, userDid string, linkType models.RecentLinkType, target string) error {
13 _, err := e.Exec(`
14 insert into recent_links (user_did, link_type, target, visited)
15 values (?, ?, ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
16 on conflict(user_did, target) do update set
17 visited = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
18 `, userDid, string(linkType), target)
19 if err != nil {
20 return fmt.Errorf("failed to upsert recent link: %w", err)
21 }
22
23 _, err = e.Exec(`
24 delete from recent_links
25 where user_did = ?
26 and id not in (
27 select id from recent_links
28 where user_did = ?
29 order by visited desc
30 limit 5
31 )
32 `, userDid, userDid)
33 if err != nil {
34 return fmt.Errorf("failed to trim recent links: %w", err)
35 }
36
37 return nil
38}
39
40func GetRecentLinks(e Execer, filters ...orm.Filter) ([]*models.RecentLink, error) {
41 var conditions []string
42 var args []any
43
44 for _, filter := range filters {
45 conditions = append(conditions, filter.Condition())
46 args = append(args, filter.Arg()...)
47 }
48
49 whereClause := ""
50 if len(conditions) > 0 {
51 whereClause = "WHERE " + conditions[0]
52 for _, condition := range conditions[1:] {
53 whereClause += " AND " + condition
54 }
55 }
56
57 args = append(args, 5)
58
59 query := fmt.Sprintf(`
60 select id, user_did, link_type, target, visited
61 from recent_links
62 %s
63 order by visited desc
64 limit ?
65 `, whereClause)
66
67 rows, err := e.QueryContext(context.Background(), query, args...)
68 if err != nil {
69 return nil, fmt.Errorf("failed to query recent links: %w", err)
70 }
71 defer rows.Close()
72
73 var links []*models.RecentLink
74 for rows.Next() {
75 var l models.RecentLink
76 var linkTypeStr string
77 var visitedStr string
78 if err := rows.Scan(&l.Id, &l.UserDid, &linkTypeStr, &l.Target, &visitedStr); err != nil {
79 return nil, fmt.Errorf("failed to scan recent link: %w", err)
80 }
81 l.LinkType = models.RecentLinkType(linkTypeStr)
82 l.Visited, err = time.Parse(time.RFC3339, visitedStr)
83 if err != nil {
84 return nil, fmt.Errorf("failed to parse visited timestamp: %w", err)
85 }
86 links = append(links, &l)
87 }
88
89 return links, nil
90}