Merge pull request 'ImplDiscordStuff' (#1) from ImplDiscordStuff into main
Reviewed-on: #1
This commit was merged in pull request #1.
	This commit is contained in:
		@@ -1,6 +1,8 @@
 | 
			
		||||
[discord]
 | 
			
		||||
client = ""
 | 
			
		||||
token = ""
 | 
			
		||||
appid = ""
 | 
			
		||||
guildid = ""
 | 
			
		||||
category_id = ""
 | 
			
		||||
 | 
			
		||||
[database]
 | 
			
		||||
host = ""
 | 
			
		||||
@@ -9,3 +11,4 @@ name = ""
 | 
			
		||||
username = ""
 | 
			
		||||
password = ""
 | 
			
		||||
 | 
			
		||||
admin_roles = [""]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 (
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										393
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										393
									
								
								main.go
									
									
									
									
									
								
							@@ -1,25 +1,36 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"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
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	Discord  Discord  `toml:"discord"`
 | 
			
		||||
	Database Database `toml:"database"`
 | 
			
		||||
	Discord    Discord    `toml:"discord"`
 | 
			
		||||
	Database   Database   `toml:"database"`
 | 
			
		||||
	AdminRoles []string   `toml:"admin_roles"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Discord struct {
 | 
			
		||||
	Token   string `toml:"client"`
 | 
			
		||||
	GuildID string `toml:"guildid"`
 | 
			
		||||
	Token      string `toml:"token"`
 | 
			
		||||
	AppID      string `toml:"appid"`
 | 
			
		||||
	GuildID    string `toml:"guildid"`
 | 
			
		||||
	CategoryID string `toml:"category_id"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Database struct {
 | 
			
		||||
@@ -30,42 +41,392 @@ 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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func reset(userNickname, softwareType string) {
 | 
			
		||||
	log.Printf("Resetting %s for user %s\n", softwareType, userNickname)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getUsernameFromMember(member *discordgo.Member) string {
 | 
			
		||||
	if member == nil {
 | 
			
		||||
		return "UnknownUser"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var userName string
 | 
			
		||||
	if member.Nick != "" {
 | 
			
		||||
		userName = member.Nick
 | 
			
		||||
	} else if member.User != nil && member.User.Username != "" {
 | 
			
		||||
		userName = member.User.Username
 | 
			
		||||
	} else {
 | 
			
		||||
		userName = "UnknownUser" 
 | 
			
		||||
	}
 | 
			
		||||
	return userName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	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)
 | 
			
		||||
			_, 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 you 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"
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			categoryID := config.Discord.CategoryID
 | 
			
		||||
			guildID := i.GuildID
 | 
			
		||||
			userID := i.Member.User.ID
 | 
			
		||||
			userName := getUsernameFromMember(i.Member)
 | 
			
		||||
 | 
			
		||||
			if !canCreateTicket(userName, selectedOption) {
 | 
			
		||||
				err := client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
					Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
					Data: &discordgo.InteractionResponseData{
 | 
			
		||||
						Content: fmt.Sprintf("You already have an active %s ticket. Please wait for the administrators to process it.", softwareType),
 | 
			
		||||
						Flags:   discordgo.MessageFlagsEphemeral,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Println("Error sending interaction response:", err)
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			channel, err := client.GuildChannelCreateComplex(guildID, discordgo.GuildChannelCreateData{
 | 
			
		||||
				Name:     fmt.Sprintf("reset-%s-%s", softwareType, userName),
 | 
			
		||||
				Type:     discordgo.ChannelTypeGuildText,
 | 
			
		||||
				ParentID: categoryID,
 | 
			
		||||
				PermissionOverwrites: []*discordgo.PermissionOverwrite{
 | 
			
		||||
					{
 | 
			
		||||
						ID:    guildID,
 | 
			
		||||
						Type:  discordgo.PermissionOverwriteTypeRole,
 | 
			
		||||
						Deny:  discordgo.PermissionViewChannel,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error creating hwid request channel:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, roleID := range config.AdminRoles {
 | 
			
		||||
				client.ChannelPermissionSet(channel.ID, roleID, discordgo.PermissionOverwriteTypeRole, discordgo.PermissionViewChannel, 0)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: "Request submitted, you'll get a PM when it has been processed",
 | 
			
		||||
					Flags:   discordgo.MessageFlagsEphemeral,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			_, err = client.ChannelMessageSendComplex(channel.ID, &discordgo.MessageSend{
 | 
			
		||||
				Content: fmt.Sprintf("Reset request by %s for %s", userName, softwareType),
 | 
			
		||||
				Components: []discordgo.MessageComponent{
 | 
			
		||||
					discordgo.ActionsRow{
 | 
			
		||||
						Components: []discordgo.MessageComponent{
 | 
			
		||||
							discordgo.Button{
 | 
			
		||||
								Label:    "Accept",
 | 
			
		||||
								Style:    discordgo.PrimaryButton,
 | 
			
		||||
								CustomID: fmt.Sprintf("accept_%s_%s", userID, softwareType),
 | 
			
		||||
							},
 | 
			
		||||
							discordgo.Button{
 | 
			
		||||
								Label:    "Decline",
 | 
			
		||||
								Style:    discordgo.DangerButton,
 | 
			
		||||
								CustomID: fmt.Sprintf("decline_%s_%s", userID, softwareType),
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending message to the ticket channel:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"accept": func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
			data := i.MessageComponentData().CustomID
 | 
			
		||||
			parts := strings.Split(data, "_")
 | 
			
		||||
			if len(parts) != 3 {
 | 
			
		||||
				log.Println("Invalid accept button custom ID")
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			userID := parts[1]
 | 
			
		||||
			softwareType := parts[2]
 | 
			
		||||
 | 
			
		||||
			member, err := client.GuildMember(i.GuildID, userID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error fetching member info:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			userName := getUsernameFromMember(member)
 | 
			
		||||
 | 
			
		||||
			reset(userName, softwareType)
 | 
			
		||||
 | 
			
		||||
			err = client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: "Request accepted and processed.",
 | 
			
		||||
					Flags:   discordgo.MessageFlagsEphemeral,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			_, err = client.ChannelDelete(i.ChannelID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error deleting channel:", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			dmChannel, err := client.UserChannelCreate(userID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error creating DM channel:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			_, err = client.ChannelMessageSend(dmChannel.ID, fmt.Sprintf("Your reset request for %s has been accepted and processed.", softwareType))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending DM:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"decline": func(client *discordgo.Session, i *discordgo.InteractionCreate) {
 | 
			
		||||
			data := i.MessageComponentData().CustomID
 | 
			
		||||
			parts := strings.Split(data, "_")
 | 
			
		||||
			if len(parts) != 3 {
 | 
			
		||||
				log.Println("Invalid decline button custom ID")
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			userID := parts[1]
 | 
			
		||||
 | 
			
		||||
			err := client.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
 | 
			
		||||
				Type: discordgo.InteractionResponseChannelMessageWithSource,
 | 
			
		||||
				Data: &discordgo.InteractionResponseData{
 | 
			
		||||
					Content: "Request declined.",
 | 
			
		||||
					Flags:   discordgo.MessageFlagsEphemeral,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending interaction response:", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			_, err = client.ChannelDelete(i.ChannelID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error deleting channel:", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			dmChannel, err := client.UserChannelCreate(userID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error creating DM channel:", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			_, err = client.ChannelMessageSend(dmChannel.ID, "Your reset request has been declined.")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println("Error sending DM:", err)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func canCreateTicket(userName, softwareType string) bool {
 | 
			
		||||
	guildChannels, err := client.GuildChannels(config.Discord.GuildID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("Error fetching guild channels:", err)
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, channel := range guildChannels {
 | 
			
		||||
		if channel.Type == discordgo.ChannelTypeGuildText && channel.ParentID == config.Discord.CategoryID {	
 | 
			
		||||
			expectedName := fmt.Sprintf("reset-%s-%s", softwareType, userName)
 | 
			
		||||
			if channel.Name == expectedName {
 | 
			
		||||
				return false 
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
			customID := i.MessageComponentData().CustomID
 | 
			
		||||
			if h, ok := componentsHandlers[customID]; ok {
 | 
			
		||||
				h(client, i)
 | 
			
		||||
			} else if strings.HasPrefix(customID, "accept_") {
 | 
			
		||||
				componentsHandlers["accept"](client, i)
 | 
			
		||||
			} else if strings.HasPrefix(customID, "decline_") {
 | 
			
		||||
				componentsHandlers["decline"](client, i)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	err := client.Open()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Error opening connection:", err)
 | 
			
		||||
		log.Println("Error opening connection:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +434,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