Archived
1
0
Fork 0

Truncate too long product names for Twitter

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2021-03-02 08:56:47 +01:00
parent 45025def65
commit 9692da6852
No known key found for this signature in database
GPG key ID: FF42D23B580C89F7
2 changed files with 64 additions and 4 deletions

View file

@ -5,6 +5,7 @@ import (
"regexp"
"strings"
"time"
"unicode/utf8"
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
@ -12,6 +13,9 @@ import (
"gorm.io/gorm"
)
// maximum number of characters a tweet can support
const tweetMaxSize = 280
// Tweet to store relationship between a Product and a Twitter notification
type Tweet struct {
gorm.Model
@ -107,11 +111,8 @@ func formatPrice(value float64, currency string) string {
// NotifyWhenAvailable create a Twitter status for announcing that a product is available
// implements the Notifier interface
func (c *TwitterNotifier) NotifyWhenAvailable(shopName string, productName string, productPrice float64, productCurrency string, productURL string) error {
// format message
formattedPrice := formatPrice(productPrice, productCurrency)
hashtags := c.buildHashtags(productName)
message := fmt.Sprintf("%s: %s for %s is available at %s %s", shopName, productName, formattedPrice, productURL, hashtags)
message := formatAvailableTweet(shopName, productName, productPrice, productCurrency, productURL, hashtags)
// create thread
tweetID, err := c.createTweet(message)
if err != nil {
@ -129,6 +130,22 @@ func (c *TwitterNotifier) NotifyWhenAvailable(shopName string, productName strin
return nil
}
func formatAvailableTweet(shopName string, productName string, productPrice float64, productCurrency string, productURL string, hashtags string) string {
// format message
formattedPrice := formatPrice(productPrice, productCurrency)
message := fmt.Sprintf("%s: %s for %s is available at %s %s", shopName, productName, formattedPrice, productURL, hashtags)
// truncate tweet if too big
if utf8.RuneCountInString(message) > tweetMaxSize {
// maximum tweet size - other characters - additional "…" to say product name has been truncated
productNameSize := tweetMaxSize - utf8.RuneCountInString(fmt.Sprintf("%s: for %s is available at %s %s", shopName, formattedPrice, productURL, hashtags)) - 1
format := fmt.Sprintf("%%s: %%.%ds… for %%s is available at %%s %%s", productNameSize)
message = fmt.Sprintf(format, shopName, productName, formattedPrice, productURL, hashtags)
}
return message
}
// NotifyWhenNotAvailable create a Twitter status replying to the NotifyWhenAvailable status to say it's over
// implements the Notifier interface
func (c *TwitterNotifier) NotifyWhenNotAvailable(productURL string, duration time.Duration) error {

View file

@ -79,3 +79,46 @@ func TestFormatPrice(t *testing.T) {
})
}
}
/*
func formatAvailableTweet(shopName string, productName string, productPrice float64, productCurrency string, productURL string, hashtags string) string {
// format message
formattedPrice := formatPrice(productPrice, productCurrency)
message := fmt.Sprintf("%s: %s for %s is available at %s %s", shopName, productName, formattedPrice, productURL, hashtags)
// truncate tweet if too big
if utf8.RuneCountInString(message) > tweetMaxSize {
// maximum tweet size - other characters - additional "…" to say product name has been truncated
productNameSize := tweetMaxSize - utf8.RuneCountInString(fmt.Sprintf("%s: for %s is available at %s %s", shopName, formattedPrice, productURL, hashtags)) - 1
format := fmt.Sprintf("%%s: %%.%ds… for %%s is available at %%s %%s", productNameSize)
message = fmt.Sprintf(format, shopName, productName, formattedPrice, productURL, hashtags)
}
return message
}
*/
func TestFormatAvailableTweet(t *testing.T) {
tests := []struct {
shopName string
productName string
productPrice float64
productCurrency string
productURL string
hashtags string
expected string
}{
{"shop.com", "my awesome product", 999.99, "USD", "https://shop.com/awesome", "#awesome #product", "shop.com: my awesome product for $999.99 is available at https://shop.com/awesome #awesome #product"},
{"shop.com", "my awesome product with very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long name", 999.99, "USD", "https://shop.com/awesome", "#awesome #product", "shop.com: my awesome product with very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very… for $999.99 is available at https://shop.com/awesome #awesome #product"},
}
for i, tc := range tests {
t.Run(fmt.Sprintf("TestFormatAvailableTweet#%d", i), func(t *testing.T) {
got := formatAvailableTweet(tc.shopName, tc.productName, tc.productPrice, tc.productCurrency, tc.productURL, tc.hashtags)
if got != tc.expected {
t.Errorf("for %s, got '%s', want '%s'", tc.productName, got, tc.expected)
} else {
t.Logf("for %s, got '%s', want '%s'", tc.productName, got, tc.expected)
}
})
}
}