Truncate too long product names for Twitter
Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
45025def65
commit
9692da6852
2 changed files with 64 additions and 4 deletions
25
twitter.go
25
twitter.go
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue