all repos — disgord @ 532569a1ea202c5e56710cedc078d2b8f37f7900

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/bwmarrin/discordgo"
 15	"github.com/kkdai/youtube/v2"
 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 *youtube.Video) string {
 62	return fmt.Sprintf("**%s** (`%s`)", v.Title, v.Duration.String())
 63}
 64
 65func ParseUserMessage(messageContent, guildID string) (command string, args []string, ok bool) {
 66	after, found := strings.CutPrefix(messageContent, GetPrefix(guildID))
 67	if !found {
 68		return
 69	}
 70
 71	userInput := strings.Split(after, " ")
 72	command = strings.ToLower(userInput[0])
 73	return command, userInput[1:], len(command) > 0
 74}
 75
 76func GetPrefix(guildID string) string {
 77	for _, prefix := range Config.Values.Prefixes {
 78		if prefix.Name == guildID {
 79			return prefix.Value
 80		}
 81	}
 82
 83	Config.Values.Prefixes = append(Config.Values.Prefixes, KeyValuePair{Name: guildID, Value: defaultPrefix})
 84	err := Config.Save()
 85	if err != nil {
 86		logger.Errorf("could not save config: %s", err)
 87	}
 88	return defaultPrefix
 89}
 90
 91func SetPrefix(guildID, prefixValue string) string {
 92	var found bool
 93	for i, prefix := range Config.Values.Prefixes {
 94		if prefix.Name == guildID {
 95			Config.Values.Prefixes[i].Value = prefixValue
 96			found = true
 97			break
 98		}
 99	}
100
101	if !found {
102		Config.Values.Prefixes = append(Config.Values.Prefixes, KeyValuePair{Name: guildID, Value: prefixValue})
103	}
104
105	err := Config.Save()
106	if err != nil {
107		logger.Errorf("could not save config: %s", err)
108	}
109	return defaultPrefix
110}
111
112func Search(query string) (videoID string, err error) {
113	escaped := url.QueryEscape(strings.ToLower(strings.TrimSpace(query)))
114
115	cached, err := searchKS.Get(escaped)
116	if err == nil && cached != nil {
117		return *cached, nil
118	}
119
120	resp, err := http.Get("https://www.youtube.com/results?search_query=" + escaped)
121	if err != nil {
122		return
123	}
124	defer resp.Body.Close()
125
126	pageContent, err := io.ReadAll(resp.Body)
127	if err != nil {
128		return
129	}
130
131	matches := searchPattern.FindAllStringSubmatch(string(pageContent), -1)
132	if len(matches) == 0 {
133		err = errors.New("no video found")
134		return
135	}
136
137	videoID = matches[0][1]
138	searchKS.Set(escaped, videoID, 11*time.Hour)
139
140	return matches[0][1], nil
141}