mastodon-markdown-archive/client/client.go

159 lines
3.3 KiB
Go
Raw Normal View History

2024-05-13 08:47:26 +00:00
package client
import (
"fmt"
"net/url"
"strings"
)
type Client struct {
2024-05-18 21:35:15 +00:00
handle string
baseURL string
filters PostsFilter
account Account
// Map of Post.InReplyToId:PostId. Tracks the replies on a 1:1 basis.
replies map[string]string
// List of Post.Id. Tracks posts whose parent is not within the bounds of
// the returned posts.
orphans []string
// Map of Post.Id:*Post.
postIdMap map[string]*Post
// List of Post.Id. Tracks the posts which will be written as individual files.
output []string
2024-05-13 08:47:26 +00:00
}
type PostsFilter struct {
ExcludeReplies bool
ExcludeReblogs bool
Limit int
SinceId string
MinId string
MaxId string
}
func New(userURL string, filters PostsFilter, threaded bool) (Client, error) {
var client Client
parsedURL, err := url.Parse(userURL)
if err != nil {
return client, fmt.Errorf("error parsing user url: %w", err)
}
baseURL := fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
acc := strings.TrimPrefix(parsedURL.Path, "/")
handle := strings.TrimPrefix(acc, "@")
2024-05-18 14:08:07 +00:00
account, err := FetchAccount(baseURL, handle)
2024-05-13 08:47:26 +00:00
if err != nil {
return client, err
}
2024-05-18 14:08:07 +00:00
posts, err := FetchPosts(baseURL, account.Id, filters)
2024-05-13 08:47:26 +00:00
if err != nil {
return client, err
}
2024-05-18 21:35:15 +00:00
postIdMap := make(map[string]*Post)
2024-05-13 08:47:26 +00:00
var orphans []string
2024-05-18 21:35:15 +00:00
var output []string
for i := range posts {
post := posts[i]
postIdMap[post.Id] = &post
if !threaded {
output = append(output, post.Id)
}
}
2024-05-13 08:47:26 +00:00
client = Client{
2024-05-18 13:22:23 +00:00
baseURL: baseURL,
handle: handle,
filters: filters,
account: account,
2024-05-18 21:35:15 +00:00
postIdMap: postIdMap,
2024-05-18 13:22:23 +00:00
replies: make(map[string]string),
orphans: orphans,
2024-05-18 21:35:15 +00:00
output: output,
2024-05-13 08:47:26 +00:00
}
if threaded {
2024-05-18 21:35:15 +00:00
client.threadReplies(posts)
2024-05-18 20:42:59 +00:00
if len(client.orphans) > 0 {
2024-05-18 21:35:15 +00:00
for _, postId := range client.orphans {
statusContext, err := FetchStatusContext(baseURL, postId)
2024-05-18 20:42:59 +00:00
if err != nil {
return client, err
}
top := statusContext.Ancestors[0]
2024-05-18 21:35:15 +00:00
for i := range statusContext.Ancestors[1:] {
post := statusContext.Ancestors[i+1]
client.postIdMap[post.Id] = &post
top.descendants = append(top.descendants, &post)
2024-05-18 20:42:59 +00:00
}
2024-05-18 21:35:15 +00:00
top.descendants = append(top.descendants, client.postIdMap[postId])
2024-05-18 20:42:59 +00:00
2024-05-18 21:35:15 +00:00
for i := range statusContext.Descendants {
post := statusContext.Descendants[i]
2024-05-18 20:42:59 +00:00
if post.Account.Id != client.account.Id {
continue
}
2024-05-18 21:35:15 +00:00
client.postIdMap[post.Id] = &post
top.descendants = append(top.descendants, &post)
2024-05-18 20:42:59 +00:00
}
2024-05-18 21:35:15 +00:00
client.postIdMap[top.Id] = &top
client.output = append(client.output, top.Id)
2024-05-18 20:42:59 +00:00
}
}
2024-05-13 08:47:26 +00:00
}
return client, nil
}
func (c Client) Account() Account {
return c.account
}
2024-05-18 13:22:23 +00:00
func (c Client) Posts() []*Post {
var p []*Post
for _, i := range c.output {
2024-05-18 21:35:15 +00:00
p = append(p, c.postIdMap[i])
2024-05-18 13:22:23 +00:00
}
return p
2024-05-13 08:47:26 +00:00
}
2024-05-18 13:22:23 +00:00
func (c *Client) flushReplies(post *Post, descendants *[]*Post) {
if pid, ok := c.replies[post.Id]; ok {
2024-05-18 21:35:15 +00:00
reply := c.postIdMap[pid]
*descendants = append(*descendants, reply)
c.flushReplies(reply, descendants)
2024-05-13 08:47:26 +00:00
}
}
2024-05-18 21:35:15 +00:00
func (c *Client) threadReplies(posts []Post) {
for i := range posts {
post := &posts[i]
2024-05-13 08:47:26 +00:00
if post.InReplyToId == "" {
c.flushReplies(post, &post.descendants)
2024-05-18 21:35:15 +00:00
c.output = append(c.output, post.Id)
2024-05-13 08:47:26 +00:00
continue
}
2024-05-18 13:22:23 +00:00
if _, ok := c.postIdMap[post.InReplyToId]; ok {
c.replies[post.InReplyToId] = post.Id
2024-05-13 08:47:26 +00:00
} else {
c.orphans = append(c.orphans, post.Id)
}
}
}