all repos — disgord @ 0769e5ef6b52a3e567e837fe232691bc6e57f912

A simple Discord bot in Go.

src/globals/utils.go (view raw)

  1package globals
  2
  3import (
  4	"errors"
  5	"fmt"
  6	"io"
  7	"net/http"
  8	"net/url"
  9	"regexp"
 10	"strings"
 11	"time"
 12
 13	"github.com/birabittoh/myks"
 14	"github.com/birabittoh/rabbitpipe"
 15	"github.com/bwmarrin/discordgo"
 16)
 17
 18var (
 19	searchPattern = regexp.MustCompile(`watch\?v\x3d([a-zA-Z0-9_-]{11})`)
 20	searchKS      = myks.New[string](12 * time.Hour)
 21)
 22
 23func GetVoiceChannelID(s *discordgo.Session, m *discordgo.MessageCreate) (response string, g *discordgo.Guild, voiceChannelID string) {
 24	if m.Member == nil {
 25		response = "Please, use this inside a server."
 26		return
 27	}
 28
 29	g, err := s.State.Guild(m.GuildID)
 30	if err != nil {
 31		logger.Errorf("could not get guild: %s", err)
 32		response = MsgError
 33		return
 34	}
 35
 36	for _, vs := range g.VoiceStates {
 37		if vs.UserID == m.Author.ID {
 38			voiceChannelID = vs.ChannelID
 39			break
 40		}
 41	}
 42
 43	if voiceChannelID == "" {
 44		response = "You need to be in a voice channel to use this command."
 45	}
 46	return
 47}
 48
 49func (bc BotCommand) FormatHelp(command, guildID string) string {
 50	var shortCodeStr string
 51	if bc.ShortCode != "" {
 52		shortCodeStr = fmt.Sprintf(" (%s)", FormatCommand(bc.ShortCode, guildID))
 53	}
 54	return fmt.Sprintf(MsgHelpFmt, FormatCommand(command, guildID)+shortCodeStr, bc.Help)
 55}
 56
 57func FormatCommand(command, guildID string) string {
 58	return fmt.Sprintf("`%s%s`", GetPrefix(guildID), command)
 59}
 60
 61func FormatVideo(v *rabbitpipe.Video) string {
 62	duration := time.Duration(v.LengthSeconds) * time.Second
 63	return fmt.Sprintf("**%s** (`%s`)", v.Title, duration.String())
 64}
 65
 66func ParseUserMessage(messageContent, guildID string) (command string, args []string, ok bool) {
 67	after, found := strings.CutPrefix(messageContent, GetPrefix(guildID))
 68	if !found {
 69		return
 70	}
 71
 72	userInput := strings.Split(after, " ")
 73	command = strings.ToLower(userInput[0])
 74	return command, userInput[1:], len(command) > 0
 75}
 76
 77func GetPrefix(guildID string) string {
 78	for _, prefix := range Config.Values.Prefixes {
 79		if prefix.Name == guildID {
 80			return prefix.Value
 81		}
 82	}
 83
 84	Config.Values.Prefixes = append(Config.Values.Prefixes, KeyValuePair{Name: guildID, Value: defaultPrefix})
 85	err := Config.Save()
 86	if err != nil {
 87		logger.Errorf("could not save config: %s", err)
 88	}
 89	return defaultPrefix
 90}
 91
 92func SetPrefix(guildID, prefixValue string) string {
 93	var found bool
 94	for i, prefix := range Config.Values.Prefixes {
 95		if prefix.Name == guildID {
 96			Config.Values.Prefixes[i].Value = prefixValue
 97			found = true
 98			break
 99		}
100	}
101
102	if !found {
103		Config.Values.Prefixes = append(Config.Values.Prefixes, KeyValuePair{Name: guildID, Value: prefixValue})
104	}
105
106	err := Config.Save()
107	if err != nil {
108		logger.Errorf("could not save config: %s", err)
109	}
110	return defaultPrefix
111}
112
113func Search(query string) (videoID string, err error) {
114	escaped := url.QueryEscape(strings.ToLower(strings.TrimSpace(query)))
115
116	cached, err := searchKS.Get(escaped)
117	if err == nil && cached != nil {
118		return *cached, nil
119	}
120
121	resp, err := http.Get("https://www.youtube.com/results?search_query=" + escaped)
122	if err != nil {
123		return
124	}
125	defer resp.Body.Close()
126
127	pageContent, err := io.ReadAll(resp.Body)
128	if err != nil {
129		return
130	}
131
132	matches := searchPattern.FindAllStringSubmatch(string(pageContent), -1)
133	if len(matches) == 0 {
134		err = errors.New("no video found")
135		return
136	}
137
138	videoID = matches[0][1]
139	searchKS.Set(escaped, videoID, 11*time.Hour)
140
141	return matches[0][1], nil
142}