trying out discord slash commands
This commit is contained in:
commit
b317dfddf4
11 changed files with 326 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/pepster
|
||||||
|
/config.toml
|
||||||
|
/test.db
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
SOURCES := $(shell find . -name "*.go" -print)
|
||||||
|
BIN := pepster
|
||||||
|
|
||||||
|
$(BIN): $(SOURCES)
|
||||||
|
go build -o $@
|
53
commandLink.go
Normal file
53
commandLink.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
|
||||||
|
"pepster/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Pepster) commandLink() Command {
|
||||||
|
return Command{
|
||||||
|
Name: "link",
|
||||||
|
Description: "Links your osu! account to your Discord account.",
|
||||||
|
Options: []*CommandOption{
|
||||||
|
&CommandOption{
|
||||||
|
Type: CommandOptionString,
|
||||||
|
Name: "username",
|
||||||
|
Description: "Your osu! username",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Handler: func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
|
var user *discordgo.User
|
||||||
|
if i.User != nil {
|
||||||
|
user = i.User
|
||||||
|
} else if i.Member != nil {
|
||||||
|
user = i.Member.User
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUser := models.User{
|
||||||
|
DiscordID: user.ID,
|
||||||
|
OsuID: 2688103,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.db.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "discord_id"}},
|
||||||
|
UpdateAll: true,
|
||||||
|
}).Create(&dbUser)
|
||||||
|
fmt.Println("Updated", dbUser)
|
||||||
|
|
||||||
|
p.updateStatus <- true
|
||||||
|
|
||||||
|
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||||
|
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||||
|
Data: &discordgo.InteractionResponseData{
|
||||||
|
Content: fmt.Sprintf(":thumbsup: Linked osu! user **%s** to **%s**", "IOException", user.String()),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
97
commands.go
Normal file
97
commands.go
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEV_GUILD_ID = "665066008507187220"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Options []*CommandOption
|
||||||
|
Handler CommandHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandHandler = func(*discordgo.Session, *discordgo.InteractionCreate)
|
||||||
|
|
||||||
|
type CommandOption struct {
|
||||||
|
Type CommandOptionType
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Required bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandOptionType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
CommandOptionSubCommand CommandOptionType = 1
|
||||||
|
CommandOptionSubCommandGroup CommandOptionType = 2
|
||||||
|
CommandOptionString CommandOptionType = 3
|
||||||
|
CommandOptionInteger CommandOptionType = 4
|
||||||
|
CommandOptionBoolean CommandOptionType = 5
|
||||||
|
CommandOptionUser CommandOptionType = 6
|
||||||
|
CommandOptionChannel CommandOptionType = 7
|
||||||
|
CommandOptionRole CommandOptionType = 8
|
||||||
|
CommandOptionMentionable CommandOptionType = 9
|
||||||
|
)
|
||||||
|
|
||||||
|
func guildID(global bool) string {
|
||||||
|
if global {
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return DEV_GUILD_ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pepster) registerCommands(commands []Command, global bool) {
|
||||||
|
handlers := make(map[string]CommandHandler, len(commands))
|
||||||
|
|
||||||
|
for _, command := range commands {
|
||||||
|
convertedOptions := make([]*discordgo.ApplicationCommandOption, len(command.Options))
|
||||||
|
for i, option := range command.Options {
|
||||||
|
convertedOptions[i] = &discordgo.ApplicationCommandOption{
|
||||||
|
Name: option.Name,
|
||||||
|
Description: option.Description,
|
||||||
|
Type: discordgo.ApplicationCommandOptionType(option.Type),
|
||||||
|
Required: option.Required,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := p.discord.ApplicationCommandCreate(p.config.AppID, guildID(global), &discordgo.ApplicationCommand{
|
||||||
|
Name: command.Name,
|
||||||
|
Description: command.Description,
|
||||||
|
Options: convertedOptions,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("could not register command", command.Name, ":", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers[command.Name] = command.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
p.discord.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||||
|
if handler, ok := handlers[i.ApplicationCommandData().Name]; ok {
|
||||||
|
handler(s, i)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pepster) unregisterAllCommands(global bool) {
|
||||||
|
commands, _ := p.discord.ApplicationCommands(p.config.AppID, guildID(global))
|
||||||
|
for _, command := range commands {
|
||||||
|
p.discord.ApplicationCommandDelete(p.config.AppID, guildID(global), command.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pepster) commandsList() []Command {
|
||||||
|
return []Command{
|
||||||
|
p.commandLink(),
|
||||||
|
}
|
||||||
|
}
|
7
config.go
Normal file
7
config.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Debug bool `toml:"debug,omitempty"`
|
||||||
|
AppID string `toml:"app_id"`
|
||||||
|
BotToken string `toml:"bot_token"`
|
||||||
|
}
|
11
go.mod
Normal file
11
go.mod
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module pepster
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||||
|
github.com/bwmarrin/discordgo v0.23.3-0.20210627161652-421e14965030 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.8 // indirect
|
||||||
|
gorm.io/driver/sqlite v1.1.4 // indirect
|
||||||
|
gorm.io/gorm v1.21.12 // indirect
|
||||||
|
)
|
27
go.sum
Normal file
27
go.sum
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/bwmarrin/discordgo v0.23.3-0.20210627161652-421e14965030 h1:JgAlPJlCqsrUqXcClndnvF6LOjV528hpU/l5YzN++PA=
|
||||||
|
github.com/bwmarrin/discordgo v0.23.3-0.20210627161652-421e14965030/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||||
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
|
||||||
|
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||||
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
|
||||||
|
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
|
||||||
|
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||||
|
gorm.io/gorm v1.21.12 h1:3fQM0Eiz7jcJEhPggHEpoYnsGZqynMzverL77DV40RM=
|
||||||
|
gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
73
main.go
Normal file
73
main.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"pepster/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// open config file
|
||||||
|
configPath := flag.String("config", "config.toml", "Path to the config file (defaults to config.toml)")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
configData, err := ioutil.ReadFile(*configPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to read config file", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = toml.Unmarshal(configData, &config); err != nil {
|
||||||
|
log.Fatal("Invalid toml in config file", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// open database
|
||||||
|
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to connect database")
|
||||||
|
}
|
||||||
|
|
||||||
|
// migrate the schema
|
||||||
|
models.AutoMigrate(db)
|
||||||
|
|
||||||
|
// connect to discord
|
||||||
|
discord, err := discordgo.New("Bot " + config.BotToken)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Could not connect to discord", err)
|
||||||
|
}
|
||||||
|
if err = discord.Open(); err != nil {
|
||||||
|
log.Fatal("Could not connect to discord", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pepster := &Pepster{
|
||||||
|
config: &config,
|
||||||
|
db: db,
|
||||||
|
discord: discord,
|
||||||
|
updateStatus: make(chan bool, 5),
|
||||||
|
}
|
||||||
|
pepster.Init()
|
||||||
|
pepster.updateStatus <- true
|
||||||
|
defer pepster.Close()
|
||||||
|
|
||||||
|
// registering command handlers
|
||||||
|
pepster.registerCommands(pepster.commandsList(), false)
|
||||||
|
|
||||||
|
// graceful shutdown handler
|
||||||
|
stop := make(chan os.Signal)
|
||||||
|
signal.Notify(stop, os.Interrupt)
|
||||||
|
<-stop
|
||||||
|
log.Println("Gracefully shutting down...")
|
||||||
|
|
||||||
|
// deferred close
|
||||||
|
}
|
7
models/automigrate.go
Normal file
7
models/automigrate.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
func AutoMigrate(db *gorm.DB) {
|
||||||
|
db.AutoMigrate(&User{})
|
||||||
|
}
|
9
models/user.go
Normal file
9
models/user.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
gorm.Model
|
||||||
|
DiscordID string `gorm:"column:discord_id;unique"`
|
||||||
|
OsuID int `gorm:"column:osu_id"`
|
||||||
|
}
|
34
pepster.go
Normal file
34
pepster.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pepster struct {
|
||||||
|
config *Config
|
||||||
|
db *gorm.DB
|
||||||
|
discord *discordgo.Session
|
||||||
|
|
||||||
|
updateStatus chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pepster) Init() {
|
||||||
|
go (func() {
|
||||||
|
fmt.Println("listening")
|
||||||
|
for _ = range p.updateStatus {
|
||||||
|
_ = p.discord.UpdateStatusComplex(discordgo.UpdateStatusData{
|
||||||
|
AFK: false,
|
||||||
|
Status: "hellosu",
|
||||||
|
})
|
||||||
|
fmt.Println("lol Update")
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pepster) Close() {
|
||||||
|
p.unregisterAllCommands(false)
|
||||||
|
p.discord.Close()
|
||||||
|
}
|
Loading…
Reference in a new issue