diff --git a/bot.go b/bot.go
index 30030e9..c2660d0 100644
--- a/bot.go
+++ b/bot.go
@@ -7,7 +7,6 @@ import (
"fmt"
"log"
"math"
- "math/rand"
"net/http"
"os"
"regexp"
@@ -16,6 +15,8 @@ import (
"github.com/gotd/td/session"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/auth"
+ "github.com/gotd/td/telegram/message"
+ "github.com/gotd/td/telegram/message/html"
"github.com/gotd/td/telegram/updates"
"github.com/gotd/td/tg"
"golang.org/x/term"
@@ -33,6 +34,7 @@ type Config struct {
APIHash string `yaml:"api_hash"`
MonitoredChat int64 `yaml:"monitored_chat"`
AlertChat int64 `yaml:"alert_chat"`
+ NtfyHost string `json:"ntfy_host"`
NtfyToken string `yaml:"ntfy_token"`
NtfyTopic string `yaml:"ntfy_topic"`
SessionPath string `yaml:"session_path"`
@@ -49,6 +51,7 @@ func loadConfig(path string) (*Config, error) {
api_hash: ""
monitored_chat: 0
alert_chat: 0
+ntfy_host: "https://ntfy.sh/"
ntfy_token: ""
ntfy_topic: ""
session_path: "antiscam.session"
@@ -192,8 +195,32 @@ func escapeMarkdown(text string) string {
return result.String()
}
-func notify(message, topic, title string, priority int, token string) {
- url := "https://ntfy.zio.sh/" + topic
+func escapeHTML(text string) string {
+ var result strings.Builder
+ for _, r := range text {
+ switch r {
+ case '&':
+ result.WriteString("&")
+ case '<':
+ result.WriteString("<")
+ case '>':
+ result.WriteString(">")
+ case '"':
+ result.WriteString(""")
+ case '\'':
+ result.WriteString("'")
+ default:
+ result.WriteRune(r)
+ }
+ }
+ return result.String()
+}
+
+func notify(message, host, topic, title string, priority int, token string) {
+ if !strings.HasSuffix(host, "/") {
+ host = host + "/"
+ }
+ url := host + topic
req, err := http.NewRequest("POST", url, bytes.NewBufferString(message))
if err != nil {
log.Printf("notify: creating request: %v", err)
@@ -390,21 +417,29 @@ func handleNewMessage(ctx context.Context, api *tg.Client, alertPeer *tg.InputPe
// Get supergroup name
chatName := channel.Title
- // Build and send alert message
- matchMessage := fmt.Sprintf("🚨 Matched\n**Score**: %.2f\n**Chat**: %s (ID: %d)\n**User**: %s (%s) (ID: %d)\n",
- result.score, escapeMarkdown(chatName), chatID, escapeMarkdown(displayName+" ("+username+")"), username, senderID)
+ // Build alert message with HTML formatting for markdown v2
+ matchMessageHTML := fmt.Sprintf("🚨 Matched\nScore: %.2f\nChat: %s (ID: %d)\nUser: %s (%s) (ID: %d)\n",
+ result.score, escapeHTML(chatName), chatID, escapeHTML(displayName+" ("+username+")"), username, senderID)
- // Send ntfy notification if config set
+ // Send ntfy notification if config set (use plain text for ntfy)
if cfg.NtfyToken != "" || cfg.NtfyTopic != "" {
- notify(matchMessage, cfg.NtfyTopic, fmt.Sprintf("Scam Alert: %s", chatName), 5, cfg.NtfyToken)
+ plainMessage := fmt.Sprintf("🚨 Matched\nScore: %.2f\nChat: %s (ID: %d)\nUser: %s (%s) (ID: %d)\n",
+ result.score, chatName, chatID, displayName+" ("+username+")", username, senderID)
+ notify(plainMessage, cfg.NtfyHost, cfg.NtfyTopic, fmt.Sprintf("Scam Alert: %s", chatName), 5, cfg.NtfyToken)
}
- // Send alert message to alert chat
- _, err = api.MessagesSendMessage(ctx, &tg.MessagesSendMessageRequest{
- Peer: alertPeer,
- Message: matchMessage,
- RandomID: rand.Int63(),
- })
+ // Create a resolver for user mentions (not needed for this message, but required by html.String)
+ userResolver := func(id int64) (tg.InputUserClass, error) {
+ return &tg.InputUserFromMessage{
+ Peer: alertPeer,
+ MsgID: 0,
+ UserID: id,
+ }, nil
+ }
+
+ // Send alert message to alert chat using StyledText with HTML
+ sender := message.NewSender(api)
+ _, err = sender.To(alertPeer).StyledText(ctx, html.String(userResolver, matchMessageHTML))
if err != nil {
log.Printf("Failed to send alert message: %v", err)
}