add files
This commit is contained in:
commit
86a1a1c006
5 changed files with 864 additions and 0 deletions
450
parse.go
Normal file
450
parse.go
Normal file
|
@ -0,0 +1,450 @@
|
|||
package blueskyclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Post struct {
|
||||
Type string `json:"$type"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Embed *Embed `json:"embed,omitempty"`
|
||||
Langs []string `json:"langs,omitempty"`
|
||||
Labels *Labels `json:"labels,omitempty"`
|
||||
Reply *Reply `json:"reply,omitempty"`
|
||||
Facets *[]Facets `json:"facets,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Subject *Record `json:"subject,omitempty"`
|
||||
Avatar *Avatar `json:"avatar,omitempty"`
|
||||
Banner *Banner `json:"banner,omitempty"`
|
||||
Description string `json:"description"`
|
||||
DisplayName string `json:"displayName"`
|
||||
PinnedPost *Record `json:"pinnedPost,omitempty"`
|
||||
Allow []struct {
|
||||
Type string `json:"$type"`
|
||||
} `json:"allow,omitempty"`
|
||||
HiddenReplies []any `json:"hiddenReplies,omitempty"`
|
||||
Post string `json:"post,omitempty"`
|
||||
}
|
||||
|
||||
type Banner struct {
|
||||
Type string `json:"$type"`
|
||||
Ref struct {
|
||||
Link string `json:"$link"`
|
||||
} `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type Avatar struct {
|
||||
Type string `json:"$type"`
|
||||
Ref struct {
|
||||
Link string `json:"$link"`
|
||||
} `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type Ref struct {
|
||||
Link string `json:"$link"`
|
||||
}
|
||||
|
||||
type Thumb struct {
|
||||
Type string `json:"$type"`
|
||||
Ref *Ref `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type External struct {
|
||||
URI string `json:"uri"`
|
||||
Thumb *Thumb `json:"thumb"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type Video struct {
|
||||
Type string `json:"$type"`
|
||||
Ref *Ref `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Type string `json:"$type"`
|
||||
Ref *Ref `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
type AspectRatio struct {
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
}
|
||||
|
||||
type Images struct {
|
||||
Alt string `json:"alt,omitempty"`
|
||||
Image *Image `json:"image"`
|
||||
AspectRatio *AspectRatio `json:"aspectRatio"`
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
Type string `json:"$type"`
|
||||
External *External `json:"external,omitempty"`
|
||||
Video *Video `json:"video,omitempty"`
|
||||
Images *[]Images `json:"images,omitempty"`
|
||||
AspectRatio *AspectRatio `json:"aspectRatio,omitempty"`
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Cid string `json:"cid,omitempty"`
|
||||
URI string `json:"uri,omitempty"`
|
||||
}
|
||||
|
||||
func (r *Record) GetDID() string {
|
||||
return strings.Split(r.URI, "/")[2]
|
||||
}
|
||||
|
||||
func (r *Record) GetCollection() string {
|
||||
return strings.Split(r.URI, "/")[3]
|
||||
}
|
||||
|
||||
func (r *Record) GetRKey() string {
|
||||
return strings.Split(r.URI, "/")[4]
|
||||
}
|
||||
|
||||
type PostRecord struct {
|
||||
Type string `json:"$type"`
|
||||
Cid string `json:"cid"`
|
||||
URI string `json:"uri"`
|
||||
Record *Record `json:"record"`
|
||||
}
|
||||
|
||||
func (r *PostRecord) GetDID() string {
|
||||
return strings.Split(r.URI, "/")[2]
|
||||
}
|
||||
|
||||
func (r *PostRecord) GetCollection() string {
|
||||
return strings.Split(r.URI, "/")[3]
|
||||
}
|
||||
|
||||
func (r *PostRecord) GetRKey() string {
|
||||
return strings.Split(r.URI, "/")[4]
|
||||
}
|
||||
|
||||
type Embed struct {
|
||||
Type string `json:"$type"`
|
||||
Media *Media `json:"media,omitempty"`
|
||||
Images *[]Images `json:"images,omitempty"`
|
||||
Video *Video `json:"video,omitempty"`
|
||||
Record *PostRecord `json:"record,omitempty"`
|
||||
External *External `json:"external,omitempty"`
|
||||
}
|
||||
|
||||
type Values struct {
|
||||
Val string `json:"val"`
|
||||
}
|
||||
|
||||
type Labels struct {
|
||||
Type string `json:"$type"`
|
||||
Values *[]Values `json:"values"`
|
||||
}
|
||||
|
||||
type Reply struct {
|
||||
Root *Record `json:"root,omitempty"`
|
||||
Parent *Record `json:"parent,omitempty"`
|
||||
}
|
||||
|
||||
type Index struct {
|
||||
ByteEnd int `json:"byteEnd"`
|
||||
ByteStart int `json:"byteStart"`
|
||||
}
|
||||
|
||||
type Features struct {
|
||||
Did string `json:"did"`
|
||||
URI string `json:"uri"`
|
||||
Tag string `json:"tag"`
|
||||
Type string `json:"$type"`
|
||||
}
|
||||
|
||||
type Facets struct {
|
||||
Type string `json:"$type"`
|
||||
Index *Index `json:"index"`
|
||||
Features *[]Features `json:"features"`
|
||||
}
|
||||
|
||||
type ParsedEmbeds struct {
|
||||
Type string
|
||||
MimeType string
|
||||
Ref string
|
||||
URI string
|
||||
Width int64
|
||||
Height int64
|
||||
}
|
||||
|
||||
type FetchedPost struct {
|
||||
URI string `json:"uri"`
|
||||
Cid string `json:"cid"`
|
||||
Author struct {
|
||||
Did string `json:"did"`
|
||||
Handle string `json:"handle"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Avatar string `json:"avatar"`
|
||||
Associated struct {
|
||||
Chat struct {
|
||||
AllowIncoming string `json:"allowIncoming"`
|
||||
} `json:"chat"`
|
||||
} `json:"associated"`
|
||||
Labels []interface{} `json:"labels"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
} `json:"author"`
|
||||
Record *Post `json:"record"`
|
||||
Embed struct {
|
||||
Type string `json:"$type"`
|
||||
Media struct {
|
||||
Type string `json:"$type"`
|
||||
Images []struct {
|
||||
Thumb string `json:"thumb"`
|
||||
Fullsize string `json:"fullsize"`
|
||||
Alt string `json:"alt"`
|
||||
AspectRatio struct {
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
} `json:"aspectRatio"`
|
||||
} `json:"images"`
|
||||
} `json:"media"`
|
||||
Record struct {
|
||||
Record struct {
|
||||
Type string `json:"$type"`
|
||||
URI string `json:"uri"`
|
||||
Cid string `json:"cid"`
|
||||
Author struct {
|
||||
Did string `json:"did"`
|
||||
Handle string `json:"handle"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Avatar string `json:"avatar"`
|
||||
Associated struct {
|
||||
Chat struct {
|
||||
AllowIncoming string `json:"allowIncoming"`
|
||||
} `json:"chat"`
|
||||
} `json:"associated"`
|
||||
Labels []interface{} `json:"labels"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
} `json:"author"`
|
||||
Value struct {
|
||||
Type string `json:"$type"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Embed struct {
|
||||
Type string `json:"$type"`
|
||||
AspectRatio struct {
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
} `json:"aspectRatio"`
|
||||
Video struct {
|
||||
Type string `json:"$type"`
|
||||
Ref struct {
|
||||
Link string `json:"$link"`
|
||||
} `json:"ref"`
|
||||
MimeType string `json:"mimeType"`
|
||||
Size int `json:"size"`
|
||||
} `json:"video"`
|
||||
} `json:"embed"`
|
||||
Facets []struct {
|
||||
Type string `json:"$type"`
|
||||
Features []struct {
|
||||
Type string `json:"$type"`
|
||||
Did string `json:"did"`
|
||||
} `json:"features"`
|
||||
Index struct {
|
||||
ByteEnd int `json:"byteEnd"`
|
||||
ByteStart int `json:"byteStart"`
|
||||
} `json:"index"`
|
||||
} `json:"facets"`
|
||||
Langs []string `json:"langs"`
|
||||
Text string `json:"text"`
|
||||
} `json:"value"`
|
||||
Labels []interface{} `json:"labels"`
|
||||
LikeCount int `json:"likeCount"`
|
||||
ReplyCount int `json:"replyCount"`
|
||||
RepostCount int `json:"repostCount"`
|
||||
QuoteCount int `json:"quoteCount"`
|
||||
IndexedAt time.Time `json:"indexedAt"`
|
||||
Embeds []struct {
|
||||
Type string `json:"$type"`
|
||||
Cid string `json:"cid"`
|
||||
Playlist string `json:"playlist"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
AspectRatio struct {
|
||||
Height int `json:"height"`
|
||||
Width int `json:"width"`
|
||||
} `json:"aspectRatio"`
|
||||
} `json:"embeds"`
|
||||
} `json:"record"`
|
||||
} `json:"record"`
|
||||
} `json:"embed"`
|
||||
ReplyCount int `json:"replyCount"`
|
||||
RepostCount int `json:"repostCount"`
|
||||
LikeCount int `json:"likeCount"`
|
||||
QuoteCount int `json:"quoteCount"`
|
||||
IndexedAt time.Time `json:"indexedAt"`
|
||||
Labels []struct {
|
||||
Src string `json:"src"`
|
||||
URI string `json:"uri"`
|
||||
Cid string `json:"cid"`
|
||||
Val string `json:"val"`
|
||||
Cts time.Time `json:"cts"`
|
||||
} `json:"labels"`
|
||||
}
|
||||
|
||||
func (b *BSky) ParsePost(post []byte) (*Post, error) {
|
||||
var p = &Post{}
|
||||
err := json.Unmarshal(post, &p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (post *Post) ProcessFacets() string {
|
||||
if post == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if post.Facets == nil {
|
||||
return post.Text
|
||||
}
|
||||
|
||||
sort.Slice((*post.Facets), func(i, j int) bool {
|
||||
return (*post.Facets)[i].Index.ByteStart < (*post.Facets)[j].Index.ByteStart
|
||||
})
|
||||
|
||||
var result strings.Builder
|
||||
lastIndex := 0
|
||||
// post.Text = html.EscapeString(post.Text)
|
||||
|
||||
for _, facet := range *post.Facets {
|
||||
start := facet.Index.ByteStart
|
||||
end := facet.Index.ByteEnd
|
||||
|
||||
result.WriteString(post.Text[lastIndex:start])
|
||||
|
||||
for _, feature := range *facet.Features {
|
||||
switch feature.Type {
|
||||
case "app.bsky.richtext.facet#mention":
|
||||
link := fmt.Sprintf(`<a href="https://bsky.app/profile/%s">%s</a>`, feature.Did, post.Text[start:end])
|
||||
result.WriteString(link)
|
||||
case "app.bsky.richtext.facet#link":
|
||||
link := fmt.Sprintf(`<a href="%s">%s</a>`, feature.URI, post.Text[start:end])
|
||||
result.WriteString(link)
|
||||
case "app.bsky.richtext.facet#tag":
|
||||
link := fmt.Sprintf(`<a href="https://bsky.app/search?q=%%23%s">%s</a>`, feature.Tag, post.Text[start:end])
|
||||
result.WriteString(link)
|
||||
default:
|
||||
result.WriteString(post.Text[start:end])
|
||||
}
|
||||
}
|
||||
lastIndex = end
|
||||
}
|
||||
result.WriteString(post.Text[lastIndex:])
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func (p *Post) GetEmbeds() *[]ParsedEmbeds {
|
||||
var parsedEmbeds = &[]ParsedEmbeds{}
|
||||
if p.Embed != nil {
|
||||
if p.Embed.Video != nil {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: p.Embed.Video.Ref.Link,
|
||||
Type: "video",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
if p.Embed.External != nil {
|
||||
if strings.Contains(p.Embed.External.URI, "media.tenor.com") {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: p.Embed.External.URI,
|
||||
Type: "external",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
}
|
||||
if p.Embed.Media != nil {
|
||||
if p.Embed.Media.Images != nil {
|
||||
for _, image := range *p.Embed.Media.Images {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: image.Image.Ref.Link,
|
||||
Type: "image",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
}
|
||||
if p.Embed.Media.Video != nil {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: p.Embed.Media.Video.Ref.Link,
|
||||
Type: "video",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
if p.Embed.Media.External != nil {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: p.Embed.Media.External.URI,
|
||||
Type: "external",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
}
|
||||
if p.Embed.Images != nil {
|
||||
for _, image := range *p.Embed.Images {
|
||||
parsedEmbed := ParsedEmbeds{
|
||||
URI: image.Image.Ref.Link,
|
||||
Type: "image",
|
||||
}
|
||||
*parsedEmbeds = append(*parsedEmbeds, parsedEmbed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return parsedEmbeds
|
||||
}
|
||||
|
||||
func (p *Post) GetMedia() *Media {
|
||||
if p.GetEmbeds() != nil {
|
||||
if p.Embed.Media != nil {
|
||||
return p.Embed.Media
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Post) GetMediaImages() *[]Images {
|
||||
if p.GetMedia() != nil {
|
||||
return p.GetMedia().Images
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Post) GetExternal() *External {
|
||||
if p.GetMedia() != nil {
|
||||
if p.GetMedia().External != nil {
|
||||
return p.GetMedia().External
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Post) IsReply() bool {
|
||||
return p.Reply != nil
|
||||
}
|
||||
|
||||
func (p *Post) IsQuotePost() bool {
|
||||
if p.Embed != nil {
|
||||
if p.Embed.Record != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue