Archived
1
0
Fork 0

Enable replies on Twitter and Telegram

By default, when a product is available, a notification is sent. When that same
product is not available, a reply is sent to the original message. With tons of
notifications, replies might be seen as flooding. This commit adds an option to
explicitly enable replies on Twitter and Telegram notifiers. By default, reply
messages are disabled.

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2021-04-01 13:14:00 +02:00
parent 26eb0af9ea
commit 305b3eeb76
No known key found for this signature in database
GPG key ID: FF42D23B580C89F7
4 changed files with 41 additions and 31 deletions

View file

@ -131,10 +131,12 @@ Options:
* `access_token`: authentication token generated for your Twitter account * `access_token`: authentication token generated for your Twitter account
* `access_token_secret`: authentication token secret generated for your Twitter account * `access_token_secret`: authentication token secret generated for your Twitter account
* `hashtags`: list of key/value used to append hashtags to each tweet. Key is the pattern to match in the product name, value is the string to append to the tweet. For example, `{"twitter": {"hashtags": [{"rtx 3090": "#nvidia #rtx3090"}]}}` will detect `rtx 3090` to append `#nvidia #rtx3090` at the end of the tweet. * `hashtags`: list of key/value used to append hashtags to each tweet. Key is the pattern to match in the product name, value is the string to append to the tweet. For example, `{"twitter": {"hashtags": [{"rtx 3090": "#nvidia #rtx3090"}]}}` will detect `rtx 3090` to append `#nvidia #rtx3090` at the end of the tweet.
* `enable_replies`: reply to original message when product is not available anymore
* `telegram` (optional): * `telegram` (optional):
* `channel_name`: send message to a channel (ex: `@channel`) * `channel_name`: send message to a channel (ex: `@channel`)
* `chat_id`: send message to a chat (ex: `1234`) * `chat_id`: send message to a chat (ex: `1234`)
* `token`: key returned by BotFather * `token`: key returned by BotFather
* `enable_replies`: reply to original message when product is not available anymore
* `include_regex` (optional): include products with a name matching this regexp * `include_regex` (optional): include products with a name matching this regexp
* `exclude_regex` (optional): exclude products with a name matching this regexp * `exclude_regex` (optional): exclude products with a name matching this regexp
* `browser_address` (optional): set headless browser address (ex: `http://127.0.0.1:9222`) * `browser_address` (optional): set headless browser address (ex: `http://127.0.0.1:9222`)

View file

@ -25,13 +25,15 @@ type TwitterConfig struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
AccessTokenSecret string `json:"access_token_secret"` AccessTokenSecret string `json:"access_token_secret"`
Hashtags []map[string]string `json:"hashtags"` Hashtags []map[string]string `json:"hashtags"`
EnableReplies bool `json:"enable_replies"`
} }
// TelegramConfig to store Telegram API key // TelegramConfig to store Telegram API key
type TelegramConfig struct { type TelegramConfig struct {
Token string `json:"token"` Token string `json:"token"`
ChatID int64 `json:"chat_id"` ChatID int64 `json:"chat_id"`
ChannelName string `json:"channel_name"` ChannelName string `json:"channel_name"`
EnableReplies bool `json:"enable_replies"`
} }
// ApiConfig to store HTTP API configuration // ApiConfig to store HTTP API configuration

View file

@ -19,11 +19,11 @@ type TelegramMessage struct {
// TelegramNotifier to manage notifications to Twitter // TelegramNotifier to manage notifications to Twitter
type TelegramNotifier struct { type TelegramNotifier struct {
db *gorm.DB db *gorm.DB
bot *telegram.BotAPI bot *telegram.BotAPI
chatID int64 chatID int64
channelName string channelName string
timeout int enableReplies bool
} }
// NewTelegramNotifier to create a Notifier with Telegram capabilities // NewTelegramNotifier to create a Notifier with Telegram capabilities
@ -42,10 +42,11 @@ func NewTelegramNotifier(config *TelegramConfig, db *gorm.DB) (*TelegramNotifier
log.Debugf("connected to telegram as %s", bot.Self.UserName) log.Debugf("connected to telegram as %s", bot.Self.UserName)
return &TelegramNotifier{ return &TelegramNotifier{
db: db, db: db,
bot: bot, bot: bot,
chatID: config.ChatID, chatID: config.ChatID,
channelName: config.ChannelName, channelName: config.ChannelName,
enableReplies: config.EnableReplies,
}, nil }, nil
} }
@ -92,15 +93,17 @@ func (n *TelegramNotifier) NotifyWhenNotAvailable(productURL string, duration ti
return nil return nil
} }
// format message if n.enableReplies {
text := fmt.Sprintf("And it's gone (%s)", duration) // format message
text := fmt.Sprintf("And it's gone (%s)", duration)
// send reply on telegram // send reply on telegram
_, err := n.sendMessage(text, m.MessageID) _, err := n.sendMessage(text, m.MessageID)
if err != nil { if err != nil {
return fmt.Errorf("failed to reply on telegram: %s", err) return fmt.Errorf("failed to reply on telegram: %s", err)
}
log.Infof("reply to telegram message %d sent", m.MessageID)
} }
log.Infof("reply to telegram message %d sent", m.MessageID)
// remove message from database // remove message from database
trx = n.db.Unscoped().Delete(&m) trx = n.db.Unscoped().Delete(&m)

View file

@ -26,10 +26,11 @@ type Tweet struct {
// TwitterNotifier to manage notifications to Twitter // TwitterNotifier to manage notifications to Twitter
type TwitterNotifier struct { type TwitterNotifier struct {
db *gorm.DB db *gorm.DB
client *twitter.Client client *twitter.Client
user *twitter.User user *twitter.User
hashtagsMap []map[string]string hashtagsMap []map[string]string
enableReplies bool
} }
// NewTwitterNotifier creates a TwitterNotifier // NewTwitterNotifier creates a TwitterNotifier
@ -57,7 +58,7 @@ func NewTwitterNotifier(c *TwitterConfig, db *gorm.DB) (*TwitterNotifier, error)
} }
log.Debugf("connected to twitter as @%s", user.ScreenName) log.Debugf("connected to twitter as @%s", user.ScreenName)
return &TwitterNotifier{client: client, user: user, hashtagsMap: c.Hashtags, db: db}, nil return &TwitterNotifier{client: client, user: user, hashtagsMap: c.Hashtags, db: db, enableReplies: c.EnableReplies}, nil
} }
// create a brand new tweet // create a brand new tweet
@ -147,15 +148,17 @@ func (c *TwitterNotifier) NotifyWhenNotAvailable(productURL string, duration tim
return nil return nil
} }
// format message if c.enableReplies {
message := fmt.Sprintf("And it's gone (%s)", duration) // format message
message := fmt.Sprintf("And it's gone (%s)", duration)
// close thread on twitter // close thread on twitter
_, err := c.replyToTweet(tweet.TweetID, message) _, err := c.replyToTweet(tweet.TweetID, message)
if err != nil { if err != nil {
return fmt.Errorf("failed to create reply tweet: %s", err) return fmt.Errorf("failed to create reply tweet: %s", err)
}
log.Infof("reply to tweet %d sent", tweet.TweetID)
} }
log.Infof("reply to tweet %d sent", tweet.TweetID)
// remove tweet from database // remove tweet from database
trx = c.db.Unscoped().Delete(&tweet) trx = c.db.Unscoped().Delete(&tweet)