Skip to content

Commit 37fc35f

Browse files
committed
feat: tweeting posts now properly mentions
1 parent 120f834 commit 37fc35f

4 files changed

Lines changed: 67 additions & 5 deletions

File tree

bluesky/blueskyapi.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ type CreatePostRecord struct {
206206
Text string `json:"text"`
207207
CreatedAt time.Time `json:"createdAt"`
208208
Reply *ReplySubject `json:"reply,omitempty"`
209+
Facets []Facet `json:"facets,omitempty"`
209210
}
210211

211212
type Subject struct {
@@ -808,11 +809,48 @@ func GetFollows(pds string, token string, context string, actor string) (*Follow
808809
}
809810

810811
// This handles both normal & replys
811-
func UpdateStatus(pds string, token string, my_did string, status string, in_reply_to *string) (*ThreadRoot, error) {
812+
func UpdateStatus(pds string, token string, my_did string, status string, in_reply_to *string, mentions []bridge.MentionParsing) (*ThreadRoot, error) {
812813
url := pds + "/xrpc/com.atproto.repo.createRecord"
813814

814815
var replySubject *ReplySubject
815816
var err error
817+
facets := []Facet{}
818+
819+
// find mention's DID
820+
handles := []string{}
821+
for _, mention := range mentions {
822+
handles = append(handles, mention.Handle)
823+
}
824+
mentionedUsers, err := GetUsersInfo(pds, token, handles, false)
825+
826+
if err == nil {
827+
for _, mention := range mentions {
828+
var mentionDID string
829+
for _, user := range mentionedUsers {
830+
if user.ScreenName == mention.Handle {
831+
mentionDID = bridge.TwitterIDToBlueSky(*user.ID) // efficency is poor
832+
break
833+
}
834+
}
835+
836+
if mentionDID == "" {
837+
continue
838+
}
839+
840+
facets = append(facets, Facet{
841+
Index: Index{
842+
ByteStart: mention.Start,
843+
ByteEnd: mention.End,
844+
},
845+
Features: []Feature{
846+
{
847+
Type: "app.bsky.richtext.facet#mention",
848+
Did: mentionDID,
849+
},
850+
},
851+
})
852+
}
853+
}
816854

817855
// Replying
818856
if in_reply_to != nil && *in_reply_to != "" {
@@ -830,6 +868,7 @@ func UpdateStatus(pds string, token string, my_did string, status string, in_rep
830868
Text: status,
831869
CreatedAt: time.Now().UTC(),
832870
Reply: replySubject,
871+
Facets: facets,
833872
},
834873
}
835874

bridge/bridge.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ type InternalSearchResult struct {
294294
Statuses []Tweet `json:"statuses"`
295295
}
296296

297+
type MentionParsing struct {
298+
Start int
299+
End int
300+
Handle string
301+
}
302+
297303
// Bluesky's API returns a letter ID for each user,
298304
// While twitter uses a numeric ID, meaning we
299305
// need to convert between the two

twitterv1/interaction.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package twitterv1
33
import (
44
"fmt"
55
"math/big"
6+
"regexp"
67
"time"
78

89
blueskyapi "github.com/Preloading/MastodonTwitterAPI/bluesky"
@@ -19,6 +20,10 @@ func status_update(c *fiber.Ctx) error {
1920
}
2021

2122
status := c.FormValue("status")
23+
24+
// Status parsing!
25+
mentions := findHandleInstances(status)
26+
2227
// trim_user := c.FormValue("trim_user") // Unused
2328
encoded_in_reply_to_status_id_str := c.FormValue("in_reply_to_status_id")
2429
encoded_in_reply_to_status_id_int := new(big.Int)
@@ -31,7 +36,7 @@ func status_update(c *fiber.Ctx) error {
3136
}
3237
}
3338

34-
thread, err := blueskyapi.UpdateStatus(*pds, *oauthToken, *my_did, status, in_reply_to_status_id)
39+
thread, err := blueskyapi.UpdateStatus(*pds, *oauthToken, *my_did, status, in_reply_to_status_id, mentions)
3540

3641
if err != nil {
3742
fmt.Println("Error:", err)
@@ -232,3 +237,17 @@ func DeleteTweet(c *fiber.Ctx) error {
232237
}(),
233238
)
234239
}
240+
241+
func findHandleInstances(input string) []bridge.MentionParsing {
242+
regex := regexp.MustCompile(`@([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?`)
243+
matches := regex.FindAllStringIndex(input, -1)
244+
results := []bridge.MentionParsing{}
245+
for _, match := range matches {
246+
results = append(results, bridge.MentionParsing{
247+
Start: match[0],
248+
End: match[1],
249+
Handle: input[match[0]+1 : match[1]], // +1 to skip the '@' character
250+
})
251+
}
252+
return results
253+
}

twitterv1/twitterv1.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package twitterv1
22

33
import (
4-
"fmt"
5-
64
blueskyapi "github.com/Preloading/MastodonTwitterAPI/bluesky"
75
"github.com/Preloading/MastodonTwitterAPI/config"
86
"github.com/gofiber/fiber/v2"
@@ -24,7 +22,7 @@ func InitServer(config *config.Config) {
2422
// Custom middleware to log request details
2523
app.Use(func(c *fiber.Ctx) error {
2624
// fmt.Println("Request Method:", c.Method())
27-
fmt.Println("Request URL:", c.OriginalURL())
25+
// fmt.Println("Request URL:", c.OriginalURL())
2826
// fmt.Println("Post Body:", string(c.Body()))
2927
// fmt.Println("Headers:", string(c.Request().Header.Header()))
3028
// fmt.Println()

0 commit comments

Comments
 (0)