Compare commits
	
		
			6 Commits
		
	
	
		
			e8a216b9d7
			...
			3abc4f3265
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						3abc4f3265
	
				 | 
					
					
						|||
| 
						
						
							
						
						e57d3ff4fe
	
				 | 
					
					
						|||
| 
						
						
							
						
						2598aa854a
	
				 | 
					
					
						|||
| 
						
						
							
						
						6de41e0180
	
				 | 
					
					
						|||
| 
						
						
							
						
						f24c836cbc
	
				 | 
					
					
						|||
| 
						
						
							
						
						9afda27ab4
	
				 | 
					
					
						
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -5,6 +5,7 @@ go 1.22.4
 | 
			
		||||
require (
 | 
			
		||||
	github.com/BurntSushi/toml v1.4.0
 | 
			
		||||
	github.com/bwmarrin/discordgo v0.28.1
 | 
			
		||||
	github.com/lib/pq v1.10.9
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										234
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										234
									
								
								main.go
									
									
									
									
									
								
							@@ -1,16 +1,25 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/BurntSushi/toml"
 | 
			
		||||
	"github.com/bwmarrin/discordgo"
 | 
			
		||||
	_ "github.com/lib/pq"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var client *discordgo.Session
 | 
			
		||||
var (
 | 
			
		||||
	config Config
 | 
			
		||||
	client *discordgo.Session
 | 
			
		||||
	db     *sql.DB
 | 
			
		||||
 | 
			
		||||
	globalCategoryID string
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	Discord  Discord  `toml:"discord"`
 | 
			
		||||
@@ -18,7 +27,8 @@ type Config struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Discord struct {
 | 
			
		||||
	Token   string `toml:"client"`
 | 
			
		||||
	Token   string `toml:"token"`
 | 
			
		||||
	AppID   string `toml:"appid"`
 | 
			
		||||
	GuildID string `toml:"guildid"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -30,42 +40,238 @@ type Database struct {
 | 
			
		||||
	Password string `toml:"password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func loadConfig(filename string) (Config, error) {
 | 
			
		||||
	var config Config
 | 
			
		||||
	_, err := toml.DecodeFile(filename, &config)
 | 
			
		||||
	return config, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	config, err := loadConfig("config.toml")
 | 
			
		||||
func connectDb(config Config) (*sql.DB, error) {
 | 
			
		||||
	connectionString := fmt.Sprintf(
 | 
			
		||||
		"host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
 | 
			
		||||
		config.Database.Host,
 | 
			
		||||
		config.Database.Port,
 | 
			
		||||
		config.Database.Username,
 | 
			
		||||
		config.Database.Password,
 | 
			
		||||
		config.Database.Name,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	db, err := sql.Open("postgres", connectionString)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Error occurred whilst trying to load config:", err)
 | 
			
		||||
		return nil, fmt.Errorf("error connecting to the database: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = db.Ping()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		db.Close()
 | 
			
		||||
		return nil, fmt.Errorf("error pinging the database: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Successfully connected to the database.")
 | 
			
		||||
	return db, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	var err error
 | 
			
		||||
	config, err = loadConfig("config.toml")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("Error occurred whilst trying to load config:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client, err = discordgo.New("Bot " + config.Discord.Token)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Error initializing bot:", err)
 | 
			
		||||
		log.Println("Error initializing bot:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	db, err = connectDb(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("Error initializing db connection:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	commands = []discordgo.ApplicationCommand{
 | 
			
		||||
		{
 | 
			
		||||
			Name:        "setup",
 | 
			
		||||
			Description: "Setup a channel for ticket creation",
 | 
			
		||||
			Options: []*discordgo.ApplicationCommandOption{
 | 
			
		||||
				{
 | 
			
		||||
					Type:        discordgo.ApplicationCommandOptionChannel,
 | 
			
		||||
					Name:        "channel",
 | 
			
		||||
					Description: "Channel for ticket creation",
 | 
			
		||||
					Required:    true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Type:        discordgo.ApplicationCommandOptionChannel,
 | 
			
		||||
					Name:        "category",
 | 
			
		||||
					Description: "Category for tickets",
 | 
			
		||||
					Required:    true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	commandsHandlers = map[string]func(client *discordgo.Session, i *discordgo.InteractionCreate){
 | 
			
		||||
		"setup": func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
			channelOption := i.ApplicationCommandData().Options[0].ChannelValue(client)
 | 
			
		||||
			categoryOption := i.ApplicationCommandData().Options[1].ChannelValue(client)
 | 
			
		||||
 | 
			
		||||
			globalCategoryID = categoryOption.ID
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
			_, err := client.ChannelMessageSendComplex(channelOption.ID, &discordgo.MessageSend{
 | 
			
		||||
				Content: "Click the button below to request a HWID reset:",
 | 
			
		||||
				Components: []discordgo.MessageComponent{
 | 
			
		||||
					discordgo.ActionsRow{
 | 
			
		||||
						Components: []discordgo.MessageComponent{
 | 
			
		||||
							discordgo.Button{
 | 
			
		||||
								Label:    "Request Reset",
 | 
			
		||||
								Style:    discordgo.PrimaryButton,
 | 
			
		||||
								CustomID: "create_ticket",
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending message to the specified channel:", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			err = client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: fmt.Sprintf("Setup completed! Request creation button has been added to %s", channelOption.Mention()),
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	componentsHandlers = map[string]func(client *discordgo.Session, i *discordgo.InteractionCreate){
 | 
			
		||||
		"create_ticket": func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
			err := client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: "For what would u like a HWID reset:",
 | 
			
		||||
					Components: []discordgo.MessageComponent{
 | 
			
		||||
						discordgo.ActionsRow{
 | 
			
		||||
							Components: []discordgo.MessageComponent{
 | 
			
		||||
								discordgo.SelectMenu{
 | 
			
		||||
									CustomID:    "select_software_type",
 | 
			
		||||
									Placeholder: "Choose which software",
 | 
			
		||||
									Options: []discordgo.SelectMenuOption{
 | 
			
		||||
										{
 | 
			
		||||
											Label:       "Vanity",
 | 
			
		||||
											Value:       "vanity",
 | 
			
		||||
											Description: "Request a vanity reset",
 | 
			
		||||
										},
 | 
			
		||||
										{
 | 
			
		||||
											Label:       "Mesa",
 | 
			
		||||
											Value:       "mesa",
 | 
			
		||||
											Description: "Request a mesa reset",
 | 
			
		||||
										},
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					Flags: discordgo.MessageFlagsEphemeral, 
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"select_software_type": func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
			selectedOption := i.MessageComponentData().Values[0]
 | 
			
		||||
			var softwareType string
 | 
			
		||||
			if selectedOption == "vanity" {
 | 
			
		||||
				softwareType = "Vanity"
 | 
			
		||||
			} else if selectedOption == "mesa" {
 | 
			
		||||
				softwareType = "Mesa"
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			guildID := i.GuildID
 | 
			
		||||
			userID := i.Member.User.ID
 | 
			
		||||
			userName := i.Member.User.Username
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
			channel, err := client.GuildChannelCreateComplex(guildID, discordgo.GuildChannelCreateData{
 | 
			
		||||
				Name:     fmt.Sprintf("reset-%s-%s", softwareType, userName),
 | 
			
		||||
				Type:     discordgo.ChannelTypeGuildText,
 | 
			
		||||
				ParentID: globalCategoryID,
 | 
			
		||||
				PermissionOverwrites: []*discordgo.PermissionOverwrite{
 | 
			
		||||
					{
 | 
			
		||||
						ID:    guildID,
 | 
			
		||||
						Type:  discordgo.PermissionOverwriteTypeRole,
 | 
			
		||||
						Deny:  discordgo.PermissionViewChannel,
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						ID:    userID,
 | 
			
		||||
						Type:  discordgo.PermissionOverwriteTypeMember,
 | 
			
		||||
						Allow: discordgo.PermissionViewChannel,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error creating hwid request channel:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: fmt.Sprintf("Request created: %s", channel.Mention()),
 | 
			
		||||
					Flags:   discordgo.MessageFlagsEphemeral,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if client == nil {
 | 
			
		||||
		fmt.Println("Bot client is not initialized")
 | 
			
		||||
		log.Println("Bot client is not initialized")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	client.AddHandler(func(client *discordgo.Session, r *discordgo.Ready) {
 | 
			
		||||
		fmt.Println("Bot is online")
 | 
			
		||||
		log.Println("Bot is online")
 | 
			
		||||
 | 
			
		||||
		cmdIDs := make(map[string]string, len(commands))
 | 
			
		||||
 | 
			
		||||
		for _, cmd := range commands {
 | 
			
		||||
			rcmd, err := client.ApplicationCommandCreate(client.State.User.ID, config.Discord.GuildID, &cmd)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatalf("Cannot create slash command %q: %v", cmd.Name, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cmdIDs[rcmd.ID] = rcmd.Name
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	client.AddHandler(func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
		if i.Type == discordgo.InteractionApplicationCommand {
 | 
			
		||||
			if h, ok := commandsHandlers[i.ApplicationCommandData().Name]; ok {
 | 
			
		||||
				h(client, i)
 | 
			
		||||
			}
 | 
			
		||||
		} else if i.Type == discordgo.InteractionMessageComponent {
 | 
			
		||||
			if h, ok := componentsHandlers[i.MessageComponentData().CustomID]; ok {
 | 
			
		||||
				h(client, i)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	err := client.Open()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Error opening connection:", err)
 | 
			
		||||
		log.Println("Error opening connection:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +279,11 @@ func main() {
 | 
			
		||||
	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
 | 
			
		||||
	<-stop
 | 
			
		||||
 | 
			
		||||
	fmt.Println("Gracefully shutting down.")
 | 
			
		||||
	log.Println("Gracefully shutting down.")
 | 
			
		||||
	client.Close()
 | 
			
		||||
 | 
			
		||||
	if db != nil {
 | 
			
		||||
		db.Close()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user