1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
package fetchers
import (
"encoding/json"
"fmt"
"llostre/backend/general"
"llostre/backend/notes"
"log/slog"
)
func FetchAppBskyFeedPosts(logger *slog.Logger, did, pdsURL, slingshotURL string, cache *Cache) ([]notes.Note, error) {
// get author of the note
profile, found := cache.GetProfile(did)
var err error
if !found {
profile, err = FetchProfile(logger, did, pdsURL, slingshotURL, cache)
}
if err != nil {
return nil, err
}
// try slingshot first if given
if slingshotURL != "" {
values, err := general.FetchRawRecordCollection(logger, did, "app.bsky.feed.post", slingshotURL)
if err != nil {
logger.Error("Fetching from slingshot failed")
} else {
return parseAppBskyFeedPostCollection(logger, values, profile, cache)
}
}
values, err := general.FetchRawRecordCollection(logger, did, "app.bsky.feed.post", pdsURL)
if err != nil {
return nil, err
}
return parseAppBskyFeedPostCollection(logger, values, profile, cache)
}
func FetchAppBskyFeedPostByURI(logger *slog.Logger, uri, slingshotURL string, cache *Cache) (*notes.Note, error) {
// check cache
if cached, found := cache.Get(uri); found {
return cached, nil
}
repo, _, _, err := general.ParseURI(uri)
// need to resolve DID to PDS
pdsURL, err := FetchPDS(repo)
if err != nil {
return nil, err
}
// get author of the note
profile, found := cache.GetProfile(repo)
if !found {
profile, err = FetchProfile(logger, repo, pdsURL, slingshotURL, cache)
}
if err != nil {
return nil, err
}
// try slingshot first if given
if slingshotURL != "" {
rawRecord, err := general.FetchRawRecordByURI(logger, uri, slingshotURL)
if err != nil {
logger.Error("fetching from slingshot failed", "error", err)
} else {
return parseAppBskyFeedPostRecord(rawRecord, profile, cache)
}
}
rawRecord, err := general.FetchRawRecordByURI(logger, uri, pdsURL)
if err != nil {
logger.Error("Fetching from PDS failed")
return nil, err
}
return parseAppBskyFeedPostRecord(rawRecord, profile, cache)
}
func parseAppBskyFeedPostRecord(rawRecord *general.RawRecord, profile *general.Profile, cache *Cache) (*notes.Note, error) {
if rawRecord == nil {
return nil, fmt.Errorf("unable to parse nil record")
}
record := notes.AppBskyFeedPostRecord{
URI: rawRecord.URI,
}
err := json.Unmarshal(rawRecord.Value, &record.Value)
if err != nil {
return nil, err
}
note, err := notes.NoteFromAppBskyFeedPostRecord(record, profile)
if err != nil {
return nil, err
}
// cache it
cache.Set(note.URI, note)
return note, nil
}
func parseAppBskyFeedPostCollection(logger *slog.Logger, records []general.RawRecord, profile *general.Profile, cache *Cache) ([]notes.Note, error) {
posts := make([]notes.Note, 0, len(records))
for _, record := range records {
note, err := parseAppBskyFeedPostRecord(&record, profile, cache)
if err != nil {
logger.Error("failed to parse post record", "error", err)
continue
}
cache.Set(note.URI, note)
posts = append(posts, *note)
}
return posts, nil
}
|