1package models
2
3import (
4 "fmt"
5
6 "github.com/bluesky-social/indigo/atproto/syntax"
7 "tangled.org/core/api/tangled"
8)
9
10type Profile struct {
11 // ids
12 ID int
13 Did string
14
15 // data
16 Description string
17 IncludeBluesky bool
18 Location string
19 Links [5]string
20 Stats [2]VanityStat
21 PinnedRepos [6]syntax.ATURI
22}
23
24func (p Profile) IsLinksEmpty() bool {
25 for _, l := range p.Links {
26 if l != "" {
27 return false
28 }
29 }
30 return true
31}
32
33func (p Profile) IsStatsEmpty() bool {
34 for _, s := range p.Stats {
35 if s.Kind != "" {
36 return false
37 }
38 }
39 return true
40}
41
42func (p Profile) IsPinnedReposEmpty() bool {
43 for _, r := range p.PinnedRepos {
44 if r != "" {
45 return false
46 }
47 }
48 return true
49}
50
51type VanityStatKind string
52
53const (
54 VanityStatMergedPRCount VanityStatKind = "merged-pull-request-count"
55 VanityStatClosedPRCount VanityStatKind = "closed-pull-request-count"
56 VanityStatOpenPRCount VanityStatKind = "open-pull-request-count"
57 VanityStatOpenIssueCount VanityStatKind = "open-issue-count"
58 VanityStatClosedIssueCount VanityStatKind = "closed-issue-count"
59 VanityStatRepositoryCount VanityStatKind = "repository-count"
60)
61
62func (v VanityStatKind) String() string {
63 switch v {
64 case VanityStatMergedPRCount:
65 return "Merged PRs"
66 case VanityStatClosedPRCount:
67 return "Closed PRs"
68 case VanityStatOpenPRCount:
69 return "Open PRs"
70 case VanityStatOpenIssueCount:
71 return "Open Issues"
72 case VanityStatClosedIssueCount:
73 return "Closed Issues"
74 case VanityStatRepositoryCount:
75 return "Repositories"
76 }
77 return ""
78}
79
80type VanityStat struct {
81 Kind VanityStatKind
82 Value uint64
83}
84
85func (p *Profile) ProfileAt() syntax.ATURI {
86 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", p.Did, tangled.ActorProfileNSID, "self"))
87}
88
89type RepoEvent struct {
90 Repo *Repo
91 Source *Repo
92}
93
94type ProfileTimeline struct {
95 ByMonth []ByMonth
96}
97
98func (p *ProfileTimeline) IsEmpty() bool {
99 if p == nil {
100 return true
101 }
102
103 for _, m := range p.ByMonth {
104 if !m.IsEmpty() {
105 return false
106 }
107 }
108
109 return true
110}
111
112type ByMonth struct {
113 RepoEvents []RepoEvent
114 IssueEvents IssueEvents
115 PullEvents PullEvents
116}
117
118func (b ByMonth) IsEmpty() bool {
119 return len(b.RepoEvents) == 0 &&
120 len(b.IssueEvents.Items) == 0 &&
121 len(b.PullEvents.Items) == 0
122}
123
124type IssueEvents struct {
125 Items []*Issue
126}
127
128type IssueEventStats struct {
129 Open int
130 Closed int
131}
132
133func (i IssueEvents) Stats() IssueEventStats {
134 var open, closed int
135 for _, issue := range i.Items {
136 if issue.Open {
137 open += 1
138 } else {
139 closed += 1
140 }
141 }
142
143 return IssueEventStats{
144 Open: open,
145 Closed: closed,
146 }
147}
148
149type PullEvents struct {
150 Items []*Pull
151}
152
153func (p PullEvents) Stats() PullEventStats {
154 var open, merged, closed int
155 for _, pull := range p.Items {
156 switch pull.State {
157 case PullOpen:
158 open += 1
159 case PullMerged:
160 merged += 1
161 case PullClosed:
162 closed += 1
163 }
164 }
165
166 return PullEventStats{
167 Open: open,
168 Merged: merged,
169 Closed: closed,
170 }
171}
172
173type PullEventStats struct {
174 Closed int
175 Open int
176 Merged int
177}