274 lines
6.8 KiB
Go
274 lines
6.8 KiB
Go
package bsky
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Post struct {
|
|
Text string `json:"text,omitempty"`
|
|
Type string `json:"$type,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"`
|
|
}
|
|
type Ref struct {
|
|
Link string `json:"$link,omitempty"`
|
|
}
|
|
type Thumb struct {
|
|
Type string `json:"$type,omitempty"`
|
|
Ref *Ref `json:"ref,omitempty"`
|
|
MimeType string `json:"mimeType,omitempty"`
|
|
Size int `json:"size,omitempty"`
|
|
}
|
|
type External struct {
|
|
URI string `json:"uri,omitempty"`
|
|
Thumb *Thumb `json:"thumb,omitempty"`
|
|
Title string `json:"title,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
}
|
|
type Video struct {
|
|
Type string `json:"$type,omitempty"`
|
|
Ref *Ref `json:"ref,omitempty"`
|
|
MimeType string `json:"mimeType,omitempty"`
|
|
Size int `json:"size,omitempty"`
|
|
}
|
|
type Image struct {
|
|
Type string `json:"$type,omitempty"`
|
|
Ref *Ref `json:"ref,omitempty"`
|
|
MimeType string `json:"mimeType,omitempty"`
|
|
Size int `json:"size,omitempty"`
|
|
}
|
|
type AspectRatio struct {
|
|
Width int `json:"width,omitempty"`
|
|
Height int `json:"height,omitempty"`
|
|
}
|
|
type Images struct {
|
|
Alt string `json:"alt,omitempty"`
|
|
Image *Image `json:"image,omitempty"`
|
|
AspectRatio *AspectRatio `json:"aspectRatio,omitempty"`
|
|
}
|
|
type Media struct {
|
|
Type string `json:"$type,omitempty"`
|
|
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"`
|
|
}
|
|
type PostRecord struct {
|
|
Type string `json:"$type,omitempty"`
|
|
Cid string `json:"cid,omitempty"`
|
|
URI string `json:"uri,omitempty"`
|
|
Record *Record `json:"record,omitempty"`
|
|
}
|
|
type Embed struct {
|
|
Type string `json:"$type,omitempty"`
|
|
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,omitempty"`
|
|
}
|
|
type Labels struct {
|
|
Type string `json:"$type,omitempty"`
|
|
Values *[]Values `json:"values,omitempty"`
|
|
}
|
|
type Root struct {
|
|
Cid string `json:"cid,omitempty"`
|
|
URI string `json:"uri,omitempty"`
|
|
}
|
|
type Parent struct {
|
|
Cid string `json:"cid,omitempty"`
|
|
URI string `json:"uri,omitempty"`
|
|
}
|
|
type Reply struct {
|
|
Root *Root `json:"root,omitempty"`
|
|
Parent *Parent `json:"parent,omitempty"`
|
|
}
|
|
type Index struct {
|
|
ByteEnd int `json:"byteEnd,omitempty"`
|
|
ByteStart int `json:"byteStart,omitempty"`
|
|
}
|
|
type Features struct {
|
|
Did string `json:"did,omitempty"`
|
|
URI string `json:"uri,omitempty"`
|
|
Tag string `json:"tag,omitempty"`
|
|
Type string `json:"$type,omitempty"`
|
|
}
|
|
type Facets struct {
|
|
Type string `json:"$type"`
|
|
Index *Index `json:"index,omitempty"`
|
|
Features *[]Features `json:"features,omitempty"`
|
|
}
|
|
|
|
type ParsedEmbeds struct {
|
|
Type string
|
|
MimeType string
|
|
Ref string
|
|
URI string
|
|
Width int64
|
|
Height int64
|
|
}
|
|
|
|
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
|
|
}
|