Skip to content

Commit

Permalink
Fix tweet content generation (#43)
Browse files Browse the repository at this point in the history
- Fix strings without spaces wouldn't get included in the tweet, made
  the splitting mechanism more naive - it now ignores spaces but should
  be less error prone.
- Fix link detection not accepting slashes as part of the links.
  • Loading branch information
boreq committed Nov 13, 2023
1 parent 91426e2 commit ae4bc4e
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 20 deletions.
20 changes: 10 additions & 10 deletions service/domain/content/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import (
"github.com/boreq/errors"
)

const (
httpColonSlashSlash = "http://"
httpsColonSlashSlash = "https://"
nostrColon = "nostr:"
nevent = "nevent"
npub = "npub"
note = "note"
)

type Token struct {
Type TokenType
Text string
Expand Down Expand Up @@ -168,15 +177,6 @@ func (l *Lexer) mergeConsecutiveTexts(tokens []Token) []Token {

type stateFn func(l *Lexer) (stateFn, error)

const (
httpColonSlashSlash = "http://"
httpsColonSlashSlash = "https://"
nostrColon = "nostr:"
nevent = "nevent"
npub = "npub"
note = "note"
)

func stateText(l *Lexer) (stateFn, error) {
for {
if l.comesNext(httpColonSlashSlash) || l.comesNext(httpsColonSlashSlash) {
Expand Down Expand Up @@ -295,7 +295,7 @@ func stateNostrLinkData(l *Lexer) (stateFn, error) {
}

func isValidLinkCharacterExcludingDot(r rune) bool {
return unicode.IsLetter(r) || unicode.IsNumber(r) || r == '%'
return unicode.IsLetter(r) || unicode.IsNumber(r) || r == '%' || r == '/'
}

func isBech32(r rune) bool {
Expand Down
10 changes: 10 additions & 0 deletions service/domain/content/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ func TestLexer(t *testing.T) {
},
},
},
{
Name: "only_link_with_path",
In: `https://example.com/path`,
Out: []content.Token{
{
Type: content.TokenTypeLink,
Text: "https://example.com/path",
},
},
},
}

for _, testCase := range testCases {
Expand Down
18 changes: 9 additions & 9 deletions service/domain/tweet_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package domain
import (
"fmt"
"strings"
"unicode/utf8"

"github.com/boreq/errors"
"github.com/planetary-social/nos-crossposting-service/service/domain/content"
Expand Down Expand Up @@ -70,17 +71,16 @@ func (g *TweetGenerator) createContent(builder *strings.Builder, elements []cont

builder.WriteString(element.Text)
case content.ElementTypeText:
for i, part := range strings.Split(element.Text, " ") {
futureTotalLength := builder.Len() + len(part)
if futureTotalLength > noteContentMaxLengthInRunes {
builder.WriteString(ellipsis)
remainingLen := noteContentMaxLengthInRunes - utf8.RuneCountInString(builder.String())
numberOfWrittenRunes := 0
for _, r := range element.Text {
builder.WriteRune(r)
numberOfWrittenRunes++

if numberOfWrittenRunes >= remainingLen {
builder.WriteString("...")
return nil
}

if i > 0 {
builder.WriteString(" ")
}
builder.WriteString(part)
}
default:
return errors.New("unknown element")
Expand Down
24 changes: 23 additions & 1 deletion service/domain/tweet_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ func TestTweetGenerator(t *testing.T) {
},
ExpectedContent: "Some text.",
},
{
Name: "not_a_reply_long_without_spaces",
Event: nostr.Event{
Kind: domain.EventKindNote.Int(),
Tags: []nostr.Tag{
[]string{"p", fixtures.SomePublicKey().Hex()},
},
Content: strings.Repeat("a", 300),
},
ExpectedContent: strings.Repeat("a", 200) + "...",
},
{
Name: "not_a_reply_long",
Event: nostr.Event{
Expand All @@ -38,7 +49,18 @@ func TestTweetGenerator(t *testing.T) {
},
Content: strings.Repeat("Some text. ", 100),
},
ExpectedContent: "Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text....",
ExpectedContent: "Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. Some text. So...",
},
{
Name: "not_a_reply_huge_link",
Event: nostr.Event{
Kind: domain.EventKindNote.Int(),
Tags: []nostr.Tag{
[]string{"p", fixtures.SomePublicKey().Hex()},
},
Content: "https://example.com/" + strings.Repeat("a", 300),
},
ExpectedContent: "...",
},
{
Name: "reply",
Expand Down

0 comments on commit ae4bc4e

Please sign in to comment.