add command and reply to when mentionned

This commit is contained in:
Guillaume Dorce 2024-09-22 19:14:43 +02:00
parent 78e6a35b03
commit 560fc41df0
1 changed files with 181 additions and 110 deletions

291
main.go
View File

@ -1,59 +1,88 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"context"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
"os" "github.com/conneroisu/groq-go"
"log" "github.com/joho/godotenv"
"log"
"math/rand"
"os"
"os/signal" "os/signal"
"syscall" "syscall"
"math/rand"
"github.com/conneroisu/groq-go"
"github.com/joho/godotenv"
) )
var ( var (
Token string Token string
GroqKey string GroqKey string
defaultThreshold = 0.1
defaultMaxTokens = 100
defaultTemperature float32 = 0.5
defaultMessagesCount = 100
commands = []*discordgo.ApplicationCommand{
{
Name: "ping",
Description: "Replies with Pong!",
},
}
commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"ping": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
log.Println("ping command")
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "Pong!",
},
})
},
}
) )
func init() { func init() {
err := godotenv.Load() err := godotenv.Load()
if err != nil { if err != nil {
log.Fatal("Error loading .env file") log.Fatal("Error loading .env file")
} }
Token = os.Getenv("DISCORD_TOKEN") Token = os.Getenv("DISCORD_TOKEN")
GroqKey = os.Getenv("GROQ_API_KEY") GroqKey = os.Getenv("GROQ_API_KEY")
if Token == "" { if Token == "" {
log.Fatal("No discord token found in .env file") log.Fatal("No discord token found in .env file")
} }
if GroqKey == "" { if GroqKey == "" {
log.Fatal("No Groq key found in .env file") log.Fatal("No Groq key found in .env file")
} }
} }
func main() { func main() {
dg, err := discordgo.New("Bot " + Token) dg, err := discordgo.New("Bot " + Token)
if err != nil { if err != nil {
log.Fatal("Error creating Discord session,", err) log.Fatal("Error creating Discord session,", err)
return return
} }
dg.AddHandler(messageCreate) dg.AddHandler(messageCreate)
dg.AddHandler(joiningGuild)
dg.AddHandler(leavingGuild)
dg.Identify.Intents = discordgo.IntentsGuildMessages dg.AddHandler(userCommand)
dg.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsGuilds
err = dg.Open() err = dg.Open()
if err != nil { if err != nil {
log.Fatal("Error opening connection,", err) log.Fatal("Error opening connection,", err)
return return
} }
log.Println("Bot is now running. Press CTRL-C to exit.") checkRegisteredCommands(dg)
log.Println("Bot is now running. Press CTRL-C to exit.")
sc := make(chan os.Signal, 1) sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-sc <-sc
@ -61,104 +90,146 @@ func main() {
dg.Close() dg.Close()
} }
func getMessages(s *discordgo.Session, channelID string, num int) ([]*discordgo.Message, error) { func checkRegisteredCommands(s *discordgo.Session) {
if (num <= 100) { for _, v := range s.State.Guilds {
messages, err := s.ChannelMessages(channelID, num, "", "", "") registerCommands(s, v.ID)
if err != nil { }
log.Println("error getting messages,", err) }
return nil, err
}
return messages, nil
}
messages := []*discordgo.Message{} func registerCommands(s *discordgo.Session, guildID string) {
for num > 0 { registeredCommands := make([]*discordgo.ApplicationCommand, len(commands))
var toGet int for i, v := range commands {
if num > 100 { cmd, err := s.ApplicationCommandCreate(s.State.User.ID, guildID, v)
toGet = 100 if err != nil {
} else { log.Panicf("Cannot create '%v' command: %v", v.Name, err)
toGet = num }
} registeredCommands[i] = cmd
lastMessage := "" }
if len(messages) > 0 { }
lastMessage = messages[len(messages)-1].ID
} func userCommand(s *discordgo.Session, i *discordgo.InteractionCreate) {
newMessages, err := s.ChannelMessages(channelID, toGet, lastMessage, "", "") handler, ok := commandHandlers[i.ApplicationCommandData().Name]
if err != nil { if !ok {
fmt.Println("error getting messages,", err) return
return nil, err }
} handler(s, i)
messages = append(messages, newMessages...) }
num -= toGet
} func joiningGuild(s *discordgo.Session, m *discordgo.GuildCreate) {
return messages, nil registerCommands(s, m.ID)
}
func leavingGuild(s *discordgo.Session, m *discordgo.GuildDelete) {
for _, v := range commands {
err := s.ApplicationCommandDelete(s.State.User.ID, m.ID, v.ID)
if err != nil {
log.Panicf("Cannot delete '%v' command: %v", v.Name, err)
}
}
}
func getMessages(s *discordgo.Session, channelID string, num int) ([]*discordgo.Message, error) {
if num <= 100 {
messages, err := s.ChannelMessages(channelID, num, "", "", "")
if err != nil {
log.Println("error getting messages,", err)
return nil, err
}
return messages, nil
}
messages := []*discordgo.Message{}
for num > 0 {
var toGet int
if num > 100 {
toGet = 100
} else {
toGet = num
}
lastMessage := ""
if len(messages) > 0 {
lastMessage = messages[len(messages)-1].ID
}
newMessages, err := s.ChannelMessages(channelID, toGet, lastMessage, "", "")
if err != nil {
fmt.Println("error getting messages,", err)
return nil, err
}
messages = append(messages, newMessages...)
num -= toGet
}
return messages, nil
} }
func botMentioned(s *discordgo.Session, m *discordgo.MessageCreate) bool { func botMentioned(s *discordgo.Session, m *discordgo.MessageCreate) bool {
for i := range m.Mentions { for i := range m.Mentions {
if m.Mentions[i].ID == s.State.User.ID { if m.Mentions[i].ID == s.State.User.ID {
return true return true
} }
} }
return false return false
} }
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == s.State.User.ID { if m.Author.ID == s.State.User.ID {
return return
} }
rand := rand.Intn(100) rand := rand.Float32()
if rand > 10 && !botMentioned(s, m){ if rand > float32(defaultThreshold) && !botMentioned(s, m) {
return return
} }
messages, err := getMessages(s, m.ChannelID, 100) messages, err := getMessages(s, m.ChannelID, 100)
if err != nil { if err != nil {
fmt.Println("error getting messages,", err) fmt.Println("error getting messages,", err)
return return
} }
messagesFormatted := "" messagesFormatted := ""
for i := range messages { for i := range messages {
if messages[i].Author.ID == s.State.User.ID { if messages[i].Author.ID == s.State.User.ID {
continue continue
} }
messagesFormatted = messagesFormatted + "<" + messages[i].Author.ID + "> " + messages[i].Content + "\n" messagesFormatted = messagesFormatted + "<" + messages[i].Author.ID + "> " + messages[i].Content + "\n"
} }
question := "Tu fais partie d'une conversation. Tu n'as pas conscience d'etre un bot. Reponds de maniere goofy. Ta reponse doit etre tres courte, une phrase ou deux.\n" question := "Tu fais partie d'une conversation. Tu n'as pas conscience d'etre un bot. Reponds de maniere goofy. Ta reponse doit etre tres courte, une phrase ou deux.\n"
question += "<messages>\n" + messagesFormatted + "\n</messages>" question += "<messages>\n" + messagesFormatted + "\n</messages>"
response, err := askGroq(context.Background(), question) response, err := askGroq(context.Background(), question)
if err != nil { if err != nil {
s.ChannelMessageSend(m.ChannelID, "There was an error getting the response.") if botMentioned(s, m) {
return s.ChannelMessageSendReply(m.ChannelID, "There was an error getting the response.", m.Reference())
} } else {
s.ChannelMessageSend(m.ChannelID, response) s.ChannelMessageSend(m.ChannelID, "There was an error getting the response.")
}
return
}
s.ChannelMessageSendReply(m.ChannelID, response, m.Reference())
} }
func askGroq(ctx context.Context, message string) (string,error) { func askGroq(ctx context.Context, message string) (string, error) {
client, err := groq.NewClient(GroqKey) client, err := groq.NewClient(GroqKey)
if err != nil { if err != nil {
fmt.Println("error creating Groq client,", err) fmt.Println("error creating Groq client,", err)
return "", err return "", err
} }
resp, err := client.CreateChatCompletion(ctx, groq.ChatCompletionRequest{ resp, err := client.CreateChatCompletion(ctx, groq.ChatCompletionRequest{
Model: groq.Llama318BInstant, Model: groq.Llama318BInstant,
Messages: []groq.ChatCompletionMessage{ Messages: []groq.ChatCompletionMessage{
{ {
Role: groq.ChatMessageRoleUser, Role: groq.ChatMessageRoleUser,
Content: message, Content: message,
}, },
}, },
MaxTokens: 100, MaxTokens: defaultMaxTokens,
}) Temperature: defaultTemperature,
if err != nil { })
fmt.Println("error creating Groq completion,", err) if err != nil {
return "", err fmt.Println("error creating Groq completion,", err)
} return "", err
}
return string(resp.Choices[0].Message.Content), nil
return string(resp.Choices[0].Message.Content), nil
} }