aboutsummaryrefslogtreecommitdiff
path: root/backend/fetchers/app.bsky.feed.go
blob: 10c08e75f36d9c30a17186fd44f158e8866aed21 (plain)
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
	author, found := cache.GetProfile(did)
	var err error
	if !found {
		author, err = FetchAppBskyActorProfile(logger, did, pdsURL, slingshotURL, cache)
	}
	if err != nil {
		return nil, err
	}

	// try slingshot first if given
	if slingshotURL != "" {
		records, err := general.FetchRawRecordCollection(logger, did, "app.bsky.feed.post", slingshotURL)
		if err != nil {
			logger.Error("Fetching from slingshot failed")
		} else {
			return parseAppBskyFeedPostCollection(logger, records, author, cache)
		}
	}

	records, err := general.FetchRawRecordCollection(logger, did, "app.bsky.feed.post", pdsURL)
	if err != nil {
		return nil, err
	}

	return parseAppBskyFeedPostCollection(logger, records, author, 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
	author, found := cache.GetProfile(repo)
	if !found {
		author, err = FetchAppBskyActorProfile(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, author, cache)
		}
	}

	rawRecord, err := general.FetchRawRecordByURI(logger, uri, pdsURL)
	if err != nil {
		logger.Error("Fetching from PDS failed")
		return nil, err
	}

	return parseAppBskyFeedPostRecord(rawRecord, author, cache)
}

func parseAppBskyFeedPostRecord(rawRecord *general.RawRecord, author *notes.Author, 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, author)
	if err != nil {
		return nil, err
	}

	// cache it
	cache.Set(note.URI, note)

	return note, nil
}

func parseAppBskyFeedPostCollection(logger *slog.Logger, records []general.RawRecord, author *notes.Author, cache *Cache) ([]notes.Note, error) {
	posts := make([]notes.Note, 0, len(records))
	for _, record := range records {
		note, err := parseAppBskyFeedPostRecord(&record, author, 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
}