feat(discord bot): added in a ping host command to get the bot going :D
more commands will be added as we continue working on this bot, including service restarts, log monitors
This commit is contained in:
@@ -1,5 +1,84 @@
|
||||
package bot
|
||||
|
||||
func main() {
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func TheBot() {
|
||||
|
||||
Token := os.Getenv("BOT_KEY")
|
||||
if Token == "" {
|
||||
fmt.Println("You must set DISCORD_TOKEN environment variable.")
|
||||
return
|
||||
}
|
||||
|
||||
// Create bot session
|
||||
dg, err := discordgo.New("Bot " + Token)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating Discord session,", err)
|
||||
return
|
||||
}
|
||||
|
||||
dg.Identify.Intents = discordgo.IntentsGuildMessages |
|
||||
discordgo.IntentsDirectMessages |
|
||||
discordgo.IntentsMessageContent | discordgo.IntentsGuilds
|
||||
|
||||
// Register messageCreate as a callback for MessageCreate events
|
||||
dg.AddHandler(interactionCreate)
|
||||
|
||||
// // Open the websocket and begin listening
|
||||
err = dg.Open()
|
||||
if err != nil {
|
||||
fmt.Println("Error opening Discord session,", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Wait here until CTRL-C or other term signal is received.
|
||||
fmt.Println("Bot is now running. Press CTRL-C to exit.")
|
||||
// Register commands, passing the session
|
||||
registerCommands(dg)
|
||||
|
||||
// sc := make(chan os.Signal, 1)
|
||||
// signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
|
||||
// <-sc
|
||||
|
||||
// // Cleanly close down the Discord session.
|
||||
// dg.Close()
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer stop()
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
cleanupCommands(dg)
|
||||
dg.Close()
|
||||
}
|
||||
|
||||
// This function will be called (due to event handler registration above)
|
||||
// every time a new message is created on any channel that the authed bot has access to.
|
||||
// func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// // ignore bots (including self)
|
||||
// if m.Author == nil || m.Author.Bot {
|
||||
// return
|
||||
// }
|
||||
|
||||
// // debug: log incoming messages so you can see them in console
|
||||
// fmt.Printf("msg from %s: %s\n", m.Author.Username, m.Content)
|
||||
|
||||
// // choose the prefix you want — here I check for "!ping"
|
||||
// if m.Content == "!ping" {
|
||||
// if _, err := s.ChannelMessageSend(m.ChannelID, "Pong!"); err != nil {
|
||||
// fmt.Println("send error:", err)
|
||||
// }
|
||||
// }
|
||||
// if m.Content == "!pong" {
|
||||
// if _, err := s.ChannelMessageSend(m.ChannelID, "Ping!"); err != nil {
|
||||
// fmt.Println("send error:", err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
64
controller/internal/bot/commands.go
Normal file
64
controller/internal/bot/commands.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
var registeredCommands = []*discordgo.ApplicationCommand{
|
||||
{
|
||||
Name: "ping",
|
||||
Description: "Ping a server to make sure it's still online.",
|
||||
Options: []*discordgo.ApplicationCommandOption{
|
||||
{
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
Name: "host",
|
||||
Description: "The server hostname or IP to ping",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// future commands can be added here
|
||||
}
|
||||
|
||||
func registerCommands(s *discordgo.Session) {
|
||||
existing, err := s.ApplicationCommands(s.State.User.ID, "")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to list existing commands:", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, cmd := range registeredCommands {
|
||||
alreadyExists := false
|
||||
for _, e := range existing {
|
||||
if e.Name == cmd.Name {
|
||||
alreadyExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if alreadyExists {
|
||||
fmt.Printf("Command '%s' already exists, skipping registration.\n", cmd.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err := s.ApplicationCommandCreate(s.State.User.ID, "", cmd)
|
||||
if err != nil {
|
||||
fmt.Printf("Cannot create command '%s': %v\n", cmd.Name, err)
|
||||
} else {
|
||||
fmt.Printf("Registered command: %s\n", cmd.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup commands on shutdown
|
||||
func cleanupCommands(s *discordgo.Session) {
|
||||
commands, err := s.ApplicationCommands(s.State.User.ID, "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, cmd := range commands {
|
||||
_ = s.ApplicationCommandDelete(s.State.User.ID, "", cmd.ID)
|
||||
}
|
||||
}
|
||||
18
controller/internal/bot/interaction.go
Normal file
18
controller/internal/bot/interaction.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func interactionCreate(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
if i.Type != discordgo.InteractionApplicationCommand {
|
||||
return
|
||||
}
|
||||
|
||||
switch i.ApplicationCommandData().Name {
|
||||
case "ping":
|
||||
// Get the host parameter
|
||||
// sending s sends the session over to pinger, then i is the interactions we send over
|
||||
HandlePingCommand(s, i)
|
||||
}
|
||||
}
|
||||
59
controller/internal/bot/ping_device.go
Normal file
59
controller/internal/bot/ping_device.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func HandlePingCommand(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
// Get the host parameter
|
||||
options := i.ApplicationCommandData().Options
|
||||
host := options[0].StringValue()
|
||||
|
||||
// Optionally, do a DNS lookup or ICMP ping
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: fmt.Sprintf("Could not resolve host `%s`: %v", host, err),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// // host is the user-provided hostname
|
||||
// pinger, err := probing.NewPinger(host)
|
||||
// if err != nil {
|
||||
// s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
// Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
// Data: &discordgo.InteractionResponseData{
|
||||
// Content: fmt.Sprintf("Error creating pinger: %v", err),
|
||||
// },
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// pinger.Count = 3
|
||||
// pinger.SetPrivileged(false) // <- key for Windows non-admin
|
||||
// err = pinger.Run()
|
||||
// if err != nil {
|
||||
// s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
// Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
// Data: &discordgo.InteractionResponseData{
|
||||
// Content: fmt.Sprintf("Error running ping: %v", err),
|
||||
// },
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// stats := pinger.Statistics()
|
||||
|
||||
// Respond with the first IP found
|
||||
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: fmt.Sprintf("Host `%s` resolves to %s ✅", host, ips[0].String()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user