Skip to content

Commit

Permalink
cmd/bsky-webhook: add support for facets
Browse files Browse the repository at this point in the history
  • Loading branch information
Erisa committed Jan 2, 2025
1 parent 34d804e commit 935da56
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
90 changes: 90 additions & 0 deletions cmd/bsky-webhook/facets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"fmt"
"slices"
"strings"
)

func bskyMessageToSlackMarkup(bskyMessage BskyMessage) (string, error) {
var slackStringBuilder strings.Builder

fragments, err := facetsToFragments(bskyMessage)
if err != nil {
return "", err
}

for _, fragment := range fragments {
if fragment.Features == nil {
slackStringBuilder.WriteString(fragment.Text)
} else {
uri := ""
for _, feature := range fragment.Features {
if feature.Type == "app.bsky.richtext.facet#link" {
uri = feature.Uri
break
} else if feature.Type == "app.bsky.richtext.facet#mention" {
uri = fmt.Sprintf("https://bsky.app/profile/%s", feature.Did)
break
} else if feature.Type == "app.bsky.richtext.facet#tag" {
uri = fmt.Sprintf("https://bsky.app/hashtag/%s", feature.Tag)
}
}
if uri != "" {
slackStringBuilder.WriteString(fmt.Sprintf("<%s|%s>", uri, fragment.Text))
} else {
slackStringBuilder.WriteString(fragment.Text)
}
}
}

return slackStringBuilder.String(), nil
}

func facetsToFragments(bskyMessage BskyMessage) ([]BskyTextFragment, error) {
facets := bskyMessage.Commit.Record.Facets
runes := []rune(bskyMessage.Commit.Record.Text)

fragments := []BskyTextFragment{}

slices.SortStableFunc(facets, func(a, b BskyFacet) int {
return a.Index.ByteStart - b.Index.ByteStart
})

textCursor := 0
facetCursor := 0

for facetCursor < len(facets) {
currentFacet := facets[facetCursor]

if textCursor < currentFacet.Index.ByteStart {
fragments = append(fragments, BskyTextFragment{Text: string(runes[textCursor:currentFacet.Index.ByteStart])})
} else if textCursor > currentFacet.Index.ByteStart {
facetCursor++
continue
}

if currentFacet.Index.ByteStart < currentFacet.Index.ByteEnd {
fragmentText := string(runes[currentFacet.Index.ByteStart:currentFacet.Index.ByteEnd])

// dont add the features if the text is blank
if strings.TrimSpace(fragmentText) == "" {
fragments = append(fragments, BskyTextFragment{
Text: string(runes[currentFacet.Index.ByteStart:currentFacet.Index.ByteEnd]),
})
} else {
fragments = append(fragments, BskyTextFragment{
Text: string(runes[currentFacet.Index.ByteStart:currentFacet.Index.ByteEnd]),
Features: currentFacet.Features,
})
}
}
textCursor = currentFacet.Index.ByteEnd
facetCursor++
}
if textCursor < len(runes) {
fragments = append(fragments, BskyTextFragment{Text: string(runes[textCursor:])})
}

return fragments, nil
}
14 changes: 13 additions & 1 deletion cmd/bsky-webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,24 @@ func getBskyProfile(ctx context.Context, bskyMessage BskyMessage, bsky *bluesky.
}

func sendToSlack(ctx context.Context, jetstreamMessageStr string, bskyMessage BskyMessage, imageURL string, profile bluesky.Profile, postTime time.Time) error {
var messageText string
var err error

if len(bskyMessage.Commit.Record.Facets) != 0 {
messageText, err = bskyMessageToSlackMarkup(bskyMessage)
if err != nil {
return err
}
} else {
messageText = bskyMessage.Commit.Record.Text
}

attachments := []SlackAttachment{
{
AuthorName: fmt.Sprintf("%s (@%s)", profile.Name, profile.Handle),
AuthorIcon: profile.AvatarURL,
AuthorLink: fmt.Sprintf("https://bsky.app/profile/%s", profile.Handle),
Text: fmt.Sprintf("%s\n<%s|View post on Bluesky ↗>", bskyMessage.Commit.Record.Text, bskyMessage.toURL(&profile.Handle)),
Text: fmt.Sprintf("%s\n<%s|View post on Bluesky ↗>", messageText, bskyMessage.toURL(&profile.Handle)),
ImageUrl: imageURL,
Footer: "Posted",
Ts: strconv.FormatInt(postTime.Unix(), 10),
Expand Down
29 changes: 26 additions & 3 deletions cmd/bsky-webhook/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ type BskyCommit struct {
}

type BskyRecord struct {
Text string `json:"text"`
Embed BskyEmbed `json:"embed"`
CreatedAtString string `json:"createdAt"`
Text string `json:"text"`
Embed BskyEmbed `json:"embed"`
CreatedAtString string `json:"createdAt"`
Facets []BskyFacet `json:"facets"`
}

type BskyEmbed struct {
Expand All @@ -50,6 +51,28 @@ type BskyImageRef struct {
Link string `json:"$link"`
}

type BskyFacet struct {
Features []BskyFacetFeatures `json:"features"`
Index BskyFacetIndex `json:"index"`
}

type BskyFacetFeatures struct {
Type string `json:"$type"`
Uri string `json:"uri"`
Did string `json:"did"`
Tag string `json:"tag"`
}

type BskyFacetIndex struct {
ByteEnd int `json:"byteEnd"`
ByteStart int `json:"byteStart"`
}

type BskyTextFragment struct {
Text string
Features []BskyFacetFeatures
}

type SlackAttachment struct {
AuthorName string `json:"author_name"`
AuthorIcon string `json:"author_icon"`
Expand Down

0 comments on commit 935da56

Please sign in to comment.