all repos — escarbot @ 4bc11dca690db617f89741a2f9ee7af2067b713d

Earthbound Café's custom Telegram bot, with lots of cool utilities built-in.

telegram/replace.go (view raw)

  1package telegram
  2
  3import (
  4	"fmt"
  5	"regexp"
  6	"strings"
  7
  8	tgbotapi "github.com/BiRabittoh/telegram-bot-api/v5"
  9)
 10
 11type Replacer struct {
 12	Regex  *regexp.Regexp
 13	Format string
 14}
 15
 16const (
 17	parseMode   = "markdown"
 18	linkMessage = "[🔗](%s) Da %s."
 19	regexFlags  = "(?i)(?m)"
 20)
 21
 22var replacers = []Replacer{
 23	{
 24		Regex:  regexp.MustCompile(regexFlags + `(?:(?:https?:)?\/\/)?(?:(?:www|m)\.)?(?:(?:youtube(?:-nocookie)?\.com|youtu.be))(?:\/(?:[\w\-]+\?v=|embed\/|live\/|v\/|shorts\/)?)([\w\-]+)`),
 25		Format: "https://y.outube.duckdns.org/%s",
 26	},
 27	{
 28		Regex:  regexp.MustCompile(regexFlags + `https?:\/\/(?:www\.)?twitter\.com\/(?:#!\/)?(.*)\/status(?:es)?\/([^\/\?\s]+)`),
 29		Format: "https://fxtwitter.com/%s/status/%s",
 30	},
 31	{
 32		Regex:  regexp.MustCompile(regexFlags + `(?:https?:\/\/)?(?:www\.)?x\.com\/(?:#!\/)?(.*)\/status(?:es)?\/([^\/\?\s]+)`),
 33		Format: "https://fixupx.com/%s/status/%s",
 34	},
 35	{
 36		Regex:  regexp.MustCompile(regexFlags + `(?:https?:\/\/)?(?:www\.)?instagram\.com\/(reels?|p)\/([\w\-]{11})[\/\?\w=&]*`),
 37		Format: "https://ddinstagram.com/%s/%s",
 38	},
 39	{
 40		Regex:  regexp.MustCompile(regexFlags + `https?:\/\/(?:(?:www)|(?:vm))?\.?tiktok\.com\/@([\w.]+)\/(?:video)\/(\d{19,})`),
 41		Format: "https://www.tnktok.com/@%s/video/%s",
 42	},
 43	{
 44		Regex:  regexp.MustCompile(regexFlags + `(?:https?:\/\/)?(?:(?:www)|(?:vm))?\.?tiktok\.com\/(?:t\/)?([\w]{9})\/?`),
 45		Format: "https://vm.tnktok.com/%s/",
 46	},
 47}
 48
 49func isInSpoiler(entities []tgbotapi.MessageEntity, offset, length int) bool {
 50	for _, s := range entities {
 51		if s.Type != "spoiler" {
 52			continue
 53		}
 54
 55		if offset < s.Offset+s.Length && offset+length > s.Offset {
 56			return true
 57		}
 58	}
 59	return false
 60}
 61
 62func parseText(text string, entities []tgbotapi.MessageEntity) (links []string) {
 63	var rawLinks string
 64	runes := []rune(text) // Convert to runes to handle emojis
 65
 66	for _, e := range entities {
 67		if e.Type == "text_link" {
 68			if isInSpoiler(entities, e.Offset, len(e.URL)) {
 69				continue
 70			}
 71			rawLinks += e.URL + "\n"
 72		} else if e.Type == "url" {
 73			if isInSpoiler(entities, e.Offset, e.Length) {
 74				continue
 75			}
 76
 77			rawLinks += string(runes[e.Offset:e.Offset+e.Length]) + "\n"
 78		}
 79	}
 80
 81	for _, replacer := range replacers {
 82		foundMatches := replacer.Regex.FindStringSubmatch(rawLinks)
 83		if len(foundMatches) == 0 {
 84			continue
 85		}
 86		captureGroups := foundMatches[1:]
 87
 88		var formatArgs []interface{}
 89		for _, match := range captureGroups {
 90			if match != "" {
 91				formatArgs = append(formatArgs, match)
 92			}
 93		}
 94
 95		formatted := fmt.Sprintf(replacer.Format, formatArgs...)
 96		links = append(links, formatted)
 97	}
 98	return links
 99}
100
101func getUserMention(user tgbotapi.User) string {
102	var name string
103	if user.UserName == "" {
104		name = strings.TrimSpace(user.FirstName + " " + user.LastName)
105	} else {
106		name = "@" + user.UserName
107	}
108	return fmt.Sprintf("[%s](tg://user?id=%d)", name, user.ID)
109}
110
111func handleLinks(bot *tgbotapi.BotAPI, message *tgbotapi.Message) {
112	links := []string{}
113
114	if len(message.Entities) > 0 {
115		textLinks := parseText(message.Text, message.Entities)
116		links = append(links, textLinks...)
117	}
118
119	if len(message.CaptionEntities) > 0 {
120		captionLinks := parseText(message.Caption, message.CaptionEntities)
121		links = append(links, captionLinks...)
122	}
123
124	if len(links) == 0 {
125		return
126	}
127
128	user := getUserMention(*message.From)
129
130	for _, link := range links {
131		text := fmt.Sprintf(linkMessage, link, user)
132		msg := tgbotapi.NewMessage(message.Chat.ID, text)
133		msg.MessageThreadID = message.MessageThreadID
134		msg.ParseMode = parseMode
135		bot.Send(msg)
136	}
137
138}