this repo has no description
1package repoinfo
2
3import (
4 "encoding/json"
5 "fmt"
6 "path"
7 "slices"
8
9 "github.com/bluesky-social/indigo/atproto/syntax"
10 "tangled.org/core/api/tangled"
11 "tangled.org/core/appview/models"
12 "tangled.org/core/appview/state/userutil"
13)
14
15func (r RepoInfo) owner() string {
16 if r.OwnerHandle != "" {
17 return r.OwnerHandle
18 } else {
19 return r.OwnerDid
20 }
21}
22
23func (r RepoInfo) FullName() string {
24 return path.Join(r.owner(), r.Name)
25}
26
27func (r RepoInfo) ownerWithoutAt() string {
28 if r.OwnerHandle != "" {
29 return r.OwnerHandle
30 } else {
31 return userutil.FlattenDid(r.OwnerDid)
32 }
33}
34
35func (r RepoInfo) FullNameWithoutAt() string {
36 return path.Join(r.ownerWithoutAt(), r.Name)
37}
38
39func (r RepoInfo) GetTabs() [][]string {
40 tabs := [][]string{
41 {"overview", "/", "square-chart-gantt"},
42 {"issues", "/issues", "circle-dot"},
43 {"pulls", "/pulls", "git-pull-request"},
44 {"pipelines", "/pipelines", "layers-2"},
45 }
46
47 if r.Roles.SettingsAllowed() {
48 tabs = append(tabs, []string{"settings", "/settings", "cog"})
49 }
50
51 return tabs
52}
53
54func (r RepoInfo) RepoAt() syntax.ATURI {
55 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", r.OwnerDid, tangled.RepoNSID, r.Rkey))
56}
57
58type RepoInfo struct {
59 Name string
60 Rkey string
61 OwnerDid string
62 OwnerHandle string
63 Description string
64 Website string
65 Topics []string
66 Knot string
67 Spindle string
68 IsStarred bool
69 Stats models.RepoStats
70 Roles RolesInRepo
71 Source *models.Repo
72 Ref string
73 CurrentDir string
74}
75
76// each tab on a repo could have some metadata:
77//
78// issues -> number of open issues etc.
79// settings -> a warning icon to setup branch protection? idk
80//
81// we gather these bits of info here, because go templates
82// are difficult to program in
83func (r RepoInfo) TabMetadata() map[string]any {
84 meta := make(map[string]any)
85
86 meta["pulls"] = r.Stats.PullCount.Open
87 meta["issues"] = r.Stats.IssueCount.Open
88
89 // more stuff?
90
91 return meta
92}
93
94type RolesInRepo struct {
95 Roles []string
96}
97
98func (r RolesInRepo) SettingsAllowed() bool {
99 return slices.Contains(r.Roles, "repo:settings")
100}
101
102func (r RolesInRepo) CollaboratorInviteAllowed() bool {
103 return slices.Contains(r.Roles, "repo:invite")
104}
105
106func (r RolesInRepo) RepoDeleteAllowed() bool {
107 return slices.Contains(r.Roles, "repo:delete")
108}
109
110func (r RolesInRepo) IsOwner() bool {
111 return slices.Contains(r.Roles, "repo:owner")
112}
113
114func (r RolesInRepo) IsCollaborator() bool {
115 return slices.Contains(r.Roles, "repo:collaborator")
116}
117
118func (r RolesInRepo) IsPushAllowed() bool {
119 return slices.Contains(r.Roles, "repo:push")
120}
121
122// PrimaryLanguage returns the first (most used) language from a list, or empty string if none
123func PrimaryLanguage(languages []interface{}) string {
124 if len(languages) == 0 {
125 return ""
126 }
127
128 // Languages are already sorted by percentage in descending order
129 // Just get the first one
130 if firstLang, ok := languages[0].(map[string]interface{}); ok {
131 if name, ok := firstLang["Name"].(string); ok {
132 return name
133 }
134 }
135
136 return ""
137}
138
139// StructuredData generates Schema.org JSON-LD structured data for the repository
140func (r RepoInfo) StructuredData(primaryLanguage string) string {
141 data := map[string]interface{}{
142 "@context": "https://schema.org",
143 "@type": "SoftwareSourceCode",
144 "name": r.Name,
145 "description": r.Description,
146 "codeRepository": "https://tangled.org/" + r.FullName(),
147 "url": "https://tangled.org/" + r.FullName(),
148 "author": map[string]interface{}{
149 "@type": "Person",
150 "name": r.owner(),
151 "url": "https://tangled.org/" + r.owner(),
152 },
153 }
154
155 // Add programming language if available
156 if primaryLanguage != "" {
157 data["programmingLanguage"] = primaryLanguage
158 }
159
160 jsonBytes, err := json.Marshal(data)
161 if err != nil {
162 return "{}"
163 }
164 return string(jsonBytes)
165}