From 3dbf9048fa4f26a09e1b8bf2029ef5abcdacce0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Mon, 18 Dec 2023 09:29:56 +0100 Subject: [PATCH] chore: option to truncate messages to maximum length (resolve #66) --- README.md | 2 ++ config/config.go | 3 +++ handlers/message.go | 13 +++++++++---- util/string.go | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 util/string.go diff --git a/README.md b/README.md index b1775ee..0835da5 100644 --- a/README.md +++ b/README.md @@ -118,9 +118,11 @@ For self-signed certificates, you'll need to pass your public key to Telegram's * `-certPath` (`string`) – Path of your SSL certificate when using webhook mode with `useHttp`. Default to none. * `-keyPath` (`string`) – Path of your private SSL key when using webhook mode with `useHttp`. Default to none. * `-dataDir` (`string`) – File system location where to store persistent data. Defaults to `.`. +* `-inlets` (`string`) – Path to folder containing config-based inlet definitions in YAML format. Defaults to `./inlets.d`. * `-blacklist` (`string`) – Path to a line-separated blacklist file containing user IDs (send `/help` to get your id). Defaults to `blacklist.txt`. * `-whitelist` (`string`) – Path to a line-separated whitelist file containing user IDs (send `/help` to get your id). Defaults to `whitelist.txt`. * `-rateLimit` (`int`) – Maximum number of messages to be delivered to each recipient per hour. Defaults to `100`. +* `-truncateMsgs` (`bool`) – Truncate too long messages to 4096 characters instead of rejecting them. Defaults to `false`. * `-metrics` (`bool`) – Whether to expose [Prometheus](https://prometheus.io) metrics under `/metrics`. Defaults to `false`. diff --git a/config/config.go b/config/config.go index ba394d7..c9e9901 100644 --- a/config/config.go +++ b/config/config.go @@ -68,6 +68,7 @@ type BotConfig struct { UrlSecret string ReqRateLimit int CmdRateLimit int + TruncateMsgs bool Address string Address6 string Disable6 bool @@ -131,6 +132,7 @@ func Get() *BotConfig { urlSecretPtr := flag.String("urlSecret", "", "Secret suffix to append to Telegram updates endpoint") reqRateLimitPtr := flag.Int("rateLimit", 100, "Max number of requests per recipient per hour") cmdRateLimitPtr := flag.Int("cmdRateLimit", 10, "Max number of chat commands to execute per hour") + truncateMsgsPtr := flag.Bool("truncateMsgs", false, "Truncate too long messages to 4096 characters instead of rejecting them") addrPtr := flag.String("address", "127.0.0.1", "IPv4 address to bind the webserver to") addr6Ptr := flag.String("address6", "::1", "IPv6 address to bind the webserver to") disable6Ptr := flag.Bool("disableIPv6", false, "Set if your device doesn't support IPv6. address6 will be ignored if this is set.") @@ -173,6 +175,7 @@ func Get() *BotConfig { UrlSecret: *urlSecretPtr, ReqRateLimit: *reqRateLimitPtr, CmdRateLimit: *cmdRateLimitPtr, + TruncateMsgs: *truncateMsgsPtr, Address: *addrPtr, Address6: *addr6Ptr, Disable6: *disable6Ptr, diff --git a/handlers/message.go b/handlers/message.go index 366cf8e..b7bb724 100644 --- a/handlers/message.go +++ b/handlers/message.go @@ -6,11 +6,13 @@ import ( "github.com/muety/telepush/model" "github.com/muety/telepush/resolvers" "github.com/muety/telepush/services" + "github.com/muety/telepush/util" "log" "net/http" "regexp" "strconv" "strings" + "unicode/utf8" ) var telegramApiErrorRegexp *regexp.Regexp @@ -39,10 +41,13 @@ func (h *MessageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if len(m.Text) > 4096 { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("message too long (max is 4096 characters)")) - return + if utf8.RuneCountInString(m.Text) > 4096 { + if !config.Get().TruncateMsgs { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("message too long (max is 4096 characters)")) + return + } + m.Text = util.TruncateInRunes(m.Text, 4096) } if params := r.Context().Value(config.KeyParams); params != nil { diff --git a/util/string.go b/util/string.go new file mode 100644 index 0000000..0df83b8 --- /dev/null +++ b/util/string.go @@ -0,0 +1,14 @@ +package util + +// TruncateInRunes truncates a string to fit the given size in Runes. +// https://github.com/prometheus/alertmanager/blob/dc1466487a537ea7cfce366b69429ac79a04a221/notify/util.go#L89 +func TruncateInRunes(s string, n int) string { + r := []rune(s) + if len(r) <= n { + return s + } + if n <= 3 { + return string(r[:n]) + } + return string(r[:n-1]) + "..." +}