this repo has no description
1package main
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "os"
9 "path"
10 "strings"
11
12 "github.com/bluesky-social/indigo/api/atproto"
13 "github.com/bluesky-social/indigo/atproto/atclient"
14 "github.com/bluesky-social/indigo/atproto/identity"
15 "github.com/bluesky-social/indigo/atproto/syntax"
16 "github.com/bluesky-social/indigo/lex/util"
17 "github.com/bluesky-social/indigo/xrpc"
18 "tangled.org/core/api/tangled"
19 "tangled.org/core/types"
20)
21
22type Config struct {
23 Handle string
24 AppPassword string
25}
26
27func loadConfig() Config {
28 handle, ok := os.LookupEnv("ATPROTO_HANDLE")
29 if !ok {
30 panic(fmt.Errorf("Environment variable 'ATPROTO_HANDLE' is not set\n"))
31 }
32
33 appPassword, ok := os.LookupEnv("ATPROTO_APP_PASSWORD")
34 if !ok {
35 panic(fmt.Errorf("Environment variable 'ATPROTO_APP_PASSWORD' is not set\n"))
36 }
37
38 return Config{
39 Handle: handle,
40 AppPassword: appPassword,
41 }
42}
43
44func getRepository(client *atclient.APIClient, handle *syntax.AtIdentifier, repositoryName string) (*tangled.Repo, string, error) {
45 repos, err := atproto.RepoListRecords(context.Background(), client, tangled.RepoNSID, "", 0, handle.String(), false)
46 if err != nil {
47 panic(err)
48 }
49
50 var repo *tangled.Repo
51 var uri string
52 for _, r := range repos.Records {
53 if r == nil {
54 continue
55 }
56 var tempRecord *tangled.Repo
57 tempRecord = r.Value.Val.(*tangled.Repo)
58 if tempRecord.Name == repositoryName {
59 repo = tempRecord
60 uri = r.Uri
61 break
62 }
63 }
64
65 if repo == nil {
66 return nil, "", fmt.Errorf("Cannot find repository %s\n", repositoryName)
67 }
68 return repo, uri, nil
69}
70
71func getTag(repo *tangled.Repo, repoUri string, tag string) (*types.TagReference, error) {
72 xrpcc := &xrpc.Client{
73 Host: fmt.Sprintf("https://%s", repo.Knot),
74 }
75 xrpcBytes, err := tangled.RepoTags(context.Background(), xrpcc, "", 0, fmt.Sprintf("%s/%s", strings.Split(repoUri, "/")[2], repo.Name))
76 if err != nil {
77 panic(err)
78 }
79
80 var result types.RepoTagsResponse
81 if err := json.Unmarshal(xrpcBytes, &result); err != nil {
82 panic(err)
83 }
84
85 var tagReference *types.TagReference
86 for _, t := range result.Tags {
87 if t.Tag != nil {
88 if t.Reference.Name == tag {
89 tagReference = t
90 }
91 }
92 }
93
94 if tagReference == nil {
95 return nil, fmt.Errorf("Cannot find a tag reference to tag %s\n", tag)
96 }
97 return tagReference, nil
98}
99
100func uploadArtifact(client *atclient.APIClient, repo *tangled.Repo, tag *types.TagReference, repoUri string, filePath string) error {
101 fileBytes, err := os.ReadFile(filePath)
102 if err != nil {
103 return err
104 }
105
106 blob, err := atproto.RepoUploadBlob(context.Background(), client, bytes.NewReader(fileBytes))
107 if err != nil {
108 return err
109 }
110
111 var artifact = tangled.RepoArtifact{
112 CreatedAt: syntax.DatetimeNow().String(),
113 Name: path.Base(filePath),
114 Repo: repoUri,
115 Tag: tag.Tag.Hash[:],
116 Artifact: blob.Blob,
117 }
118
119 record := atproto.RepoCreateRecord_Input{
120 Collection: tangled.RepoArtifactNSID,
121 Record: &util.LexiconTypeDecoder{
122 Val: &artifact,
123 },
124 Repo: strings.Split(repoUri, "/")[2],
125 }
126 _, err = atproto.RepoCreateRecord(context.Background(), client, &record)
127 if err != nil {
128 return err
129 }
130 return nil
131}
132
133func main() {
134 args := os.Args
135
136 if len(args) != 4 {
137 fmt.Fprintf(os.Stderr, "Wrong usage: %s [repo] [tag] [file]\n", os.Args[0])
138 os.Exit(1)
139 }
140
141 config := loadConfig()
142
143 handle, err := syntax.ParseAtIdentifier(config.Handle)
144 if err != nil {
145 panic(err)
146 }
147
148 client, err := atclient.LoginWithPassword(context.Background(), identity.DefaultDirectory(), *handle, config.AppPassword, "", nil)
149 if err != nil {
150 panic(err)
151 }
152
153 repo, uri, err := getRepository(client, handle, args[1])
154 if err != nil {
155 panic(err)
156 }
157
158 tag, err := getTag(repo, uri, args[2])
159 if err != nil {
160 panic(err)
161 }
162
163 if err = uploadArtifact(client, repo, tag, uri, args[3]); err != nil {
164 panic(err)
165 }
166 fmt.Println("Artifact successfuly uploaded !")
167}