commit
9fc6b4e99c
|
@ -0,0 +1,8 @@
|
|||
# GoLand
|
||||
.idea/
|
||||
|
||||
# Generated
|
||||
config/config_default.go
|
||||
|
||||
# sedbot
|
||||
sedbot*
|
|
@ -0,0 +1,24 @@
|
|||
GO ?= go
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
$(GO) fmt ./...
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
$(GO) generate ./...
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test -race ./...
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
$(GO) vet ./...
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
$(GO) build
|
||||
|
||||
.PHONY: build-all
|
||||
build-all: generate build
|
|
@ -0,0 +1,23 @@
|
|||
# SedBot
|
||||
|
||||
BirbMC Discord generi-bot.
|
||||
|
||||
## Commands
|
||||
|
||||
### Public
|
||||
|
||||
* `register <in-game name>` - Register to the Discord
|
||||
* `links` - Get a list of dynamic links
|
||||
* `<link>` - Get a specific link
|
||||
* `fired` - Check how many times Carolyn has been fired
|
||||
* `inspire` - Get a random "inspirational" message from [InspiroBot](https://inspirobot.me)
|
||||
|
||||
### Moderation
|
||||
|
||||
* `clear [<@user>] <number>` - Clear <number> messages (optionally only by @user)
|
||||
|
||||
## Building
|
||||
|
||||
```text
|
||||
make build-all
|
||||
```
|
|
@ -0,0 +1,64 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var defaultConfig = []byte("")
|
||||
|
||||
type Config struct {
|
||||
Token string `toml:"token"`
|
||||
Prefix string `toml:"prefix"`
|
||||
MCMToken string `toml:"mcm_token"`
|
||||
MCMURL string `toml:"mcm_url"`
|
||||
DBPath string `toml:"db_path"`
|
||||
|
||||
StaffRoles []string `toml:"staff_roles"`
|
||||
Links []Link `toml:"links"`
|
||||
MessageRoles []MessageRole `toml:"message_roles"`
|
||||
RegisterRole string `toml:"register_role"`
|
||||
RegisteredChannel string `toml:"registered_channel"`
|
||||
FiredRole string `toml:"fired_role"`
|
||||
}
|
||||
|
||||
type MessageRole struct {
|
||||
MessageID string `toml:"message_id"`
|
||||
RoleID string `toml:"role_id"`
|
||||
Emoji string `toml:"emoji"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Name string `toml:"name"`
|
||||
Aliases []string `toml:"aliases"`
|
||||
URL string `toml:"url"`
|
||||
}
|
||||
|
||||
func Load(configPath string) (*Config, error) {
|
||||
var err error
|
||||
var configContent []byte
|
||||
if len(configPath) == 0 {
|
||||
configPath = "sedbot.toml"
|
||||
}
|
||||
|
||||
configContent, err = ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err = ioutil.WriteFile(configPath, defaultConfig, os.ModePerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
configContent = defaultConfig
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var cfg *Config
|
||||
if err = toml.Unmarshal(configContent, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
var (
|
||||
firedBucket = []byte("fired")
|
||||
|
||||
buckets = [][]byte{
|
||||
firedBucket,
|
||||
}
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
db *bbolt.DB
|
||||
}
|
||||
|
||||
func Load(dbPath string) (*Database, error) {
|
||||
db, err := bbolt.Open(dbPath, 0600, bbolt.DefaultOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, b := range buckets {
|
||||
if err := db.Update(func(tx *bbolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists(b)
|
||||
return err
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &Database{
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Database) CheckPing(roleID string) int {
|
||||
roleIDByte := []byte(roleID)
|
||||
var idx int
|
||||
_ = db.db.View(func(tx *bbolt.Tx) error {
|
||||
num := tx.Bucket(firedBucket).Get(roleIDByte)
|
||||
if num != nil {
|
||||
if i, err := strconv.Atoi(string(num)); err == nil {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return idx
|
||||
}
|
||||
|
||||
func (db *Database) IncrementPing(roleID string) error {
|
||||
roleIDByte := []byte(roleID)
|
||||
return db.db.Update(func(tx *bbolt.Tx) error {
|
||||
idx := db.CheckPing(roleID)
|
||||
return tx.Bucket(firedBucket).Put(roleIDByte, []byte(strconv.Itoa(idx+1)))
|
||||
})
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const clearMax = 20
|
||||
|
||||
func init() {
|
||||
commands["clear"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
args := strings.Fields(cmd.message.Content)
|
||||
|
||||
var userID string
|
||||
if len(cmd.message.Mentions) > 0 {
|
||||
userID = cmd.message.Mentions[0].ID
|
||||
}
|
||||
|
||||
limitArg := 1
|
||||
if userID != "" {
|
||||
limitArg = 2
|
||||
if len(args) < 2 {
|
||||
return errors.New("this command takes needs two arguments with a mention")
|
||||
}
|
||||
} else if len(args) < 1 {
|
||||
return errors.New("this command takes one argument without a mention")
|
||||
}
|
||||
|
||||
limit, err := strconv.Atoi(args[limitArg])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if limit < 0 {
|
||||
limit = 0
|
||||
} else if limit > clearMax {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
batch := []string{cmd.message.ID}
|
||||
|
||||
var deleted int
|
||||
messages, err := cmd.session.ChannelMessages(cmd.message.ChannelID, 100, cmd.message.ID, "", "")
|
||||
for _, msg := range messages {
|
||||
if deleted == limit {
|
||||
break
|
||||
}
|
||||
|
||||
deleteMessage := true
|
||||
if userID != "" {
|
||||
deleteMessage = msg.Author.ID == userID
|
||||
}
|
||||
|
||||
if deleteMessage {
|
||||
batch = append(batch, msg.ID)
|
||||
deleted++
|
||||
}
|
||||
}
|
||||
|
||||
return cmd.session.ChannelMessagesBulkDelete(cmd.message.ChannelID, batch)
|
||||
},
|
||||
help: "Clear messages",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"go.etztech.xyz/sedbot/config"
|
||||
"go.etztech.xyz/sedbot/database"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"go.jolheiser.com/beaver"
|
||||
)
|
||||
|
||||
// Register commands to this map
|
||||
var commands = make(map[string]command)
|
||||
|
||||
type commandInit struct {
|
||||
session *discordgo.Session
|
||||
message *discordgo.Message
|
||||
config *config.Config
|
||||
database *database.Database
|
||||
}
|
||||
|
||||
type command struct {
|
||||
validate func(cmd commandInit) bool
|
||||
run func(cmd commandInit) error
|
||||
help string
|
||||
}
|
||||
|
||||
func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) {
|
||||
bot, err := discordgo.New("Bot " + cfg.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Links(cfg)
|
||||
|
||||
bot.AddHandler(commandHandler(cfg, db))
|
||||
bot.AddHandler(messageHandler(cfg, db))
|
||||
|
||||
beaver.Info("https://discord.com/api/oauth2/authorize?client_id=718905104643784825&permissions=0&redirect_uri=https%3A%2F%2Fbirbmc.com&scope=bot")
|
||||
|
||||
return bot, nil
|
||||
}
|
||||
|
||||
func sendTyping(s *discordgo.Session, channelID string) {
|
||||
if err := s.ChannelTyping(channelID); err != nil {
|
||||
beaver.Errorf("could not send typing status: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessage(s *discordgo.Session, channelID, content string) *discordgo.Message {
|
||||
msg, err := s.ChannelMessageSend(channelID, content)
|
||||
if err != nil {
|
||||
beaver.Errorf("could not send message: %v", err)
|
||||
return nil
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func isStaff(authorRoleIDs, staffRoleIDs []string) bool {
|
||||
for _, aRole := range authorRoleIDs {
|
||||
for _, sRole := range staffRoleIDs {
|
||||
if aRole == sRole {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
return func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// Ignore bots
|
||||
if m.Author.Bot {
|
||||
return
|
||||
}
|
||||
|
||||
// Check prefix
|
||||
if !strings.HasPrefix(m.Content, cfg.Prefix) {
|
||||
return
|
||||
}
|
||||
|
||||
content := m.Content[1:]
|
||||
args := strings.Fields(content)
|
||||
if len(args) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
cmdArg := strings.ToLower(args[0])
|
||||
isHelp := strings.EqualFold(cmdArg, "help")
|
||||
|
||||
cmd, ok := commands[cmdArg]
|
||||
if !ok && !isHelp {
|
||||
return
|
||||
}
|
||||
|
||||
if isHelp {
|
||||
sendMessage(s, m.ChannelID, cmd.help)
|
||||
return
|
||||
}
|
||||
|
||||
cmdInit := commandInit{
|
||||
session: s,
|
||||
message: m.Message,
|
||||
config: cfg,
|
||||
database: db,
|
||||
}
|
||||
if !cmd.validate(cmdInit) {
|
||||
sendMessage(s, m.ChannelID, "You cannot run this command.")
|
||||
return
|
||||
}
|
||||
if err := cmd.run(cmdInit); err != nil {
|
||||
sendMessage(s, m.ChannelID, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func messageHandler(cfg *config.Config, db *database.Database) func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
return func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// Ignore bots
|
||||
if m.Author.Bot {
|
||||
return
|
||||
}
|
||||
|
||||
// [FIRED] increment
|
||||
for _, role := range m.MentionRoles {
|
||||
if cfg.FiredRole == role {
|
||||
if err := db.IncrementPing(cfg.FiredRole); err != nil {
|
||||
beaver.Errorf("could not increment ping for %s: %v", cfg.FiredRole, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands["fired"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, fmt.Sprintf("Carolyn has been fired **%d** times!",
|
||||
cmd.database.CheckPing(cmd.config.FiredRole)))
|
||||
return nil
|
||||
},
|
||||
help: "Check how many times Carolyn has been fired.",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands["help"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
args := strings.Fields(cmd.message.Content)[1:]
|
||||
|
||||
var resp string
|
||||
if len(args) == 1 {
|
||||
resp = singleHelp(args[0])
|
||||
} else {
|
||||
resp = allHelp()
|
||||
}
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, resp)
|
||||
return nil
|
||||
},
|
||||
help: "HELP! HEEEEEEEEEELP!",
|
||||
}
|
||||
}
|
||||
|
||||
func singleHelp(cmd string) string {
|
||||
if c, ok := commands[cmd]; ok {
|
||||
return fmt.Sprintf("%s: %s", cmd, c.help)
|
||||
}
|
||||
return "Unknown command"
|
||||
}
|
||||
|
||||
func allHelp() string {
|
||||
helps := make([]string, 0)
|
||||
for n, c := range commands {
|
||||
helps = append(helps, fmt.Sprintf("%s: %s", n, c.help))
|
||||
}
|
||||
return strings.Join(helps, "\n")
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package discord
|
||||
|
||||
import "go.etztech.xyz/inspiro"
|
||||
|
||||
func init() {
|
||||
commands["inspire"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
sendTyping(cmd.session, cmd.message.ChannelID)
|
||||
|
||||
img, err := inspiro.Generate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, img)
|
||||
return nil
|
||||
},
|
||||
help: "Get inspired!",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.etztech.xyz/sedbot/config"
|
||||
)
|
||||
|
||||
func Links(cfg *config.Config) {
|
||||
links := make([]string, 0)
|
||||
for _, link := range cfg.Links {
|
||||
commands[link.Name] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, fmt.Sprintf("<%s>", link.URL))
|
||||
return nil
|
||||
},
|
||||
help: fmt.Sprintf("Returns the link for %s", link.Name),
|
||||
}
|
||||
links = append(links, fmt.Sprintf("%s -> %s", link.Name, link.URL))
|
||||
for _, alias := range link.Aliases {
|
||||
commands[alias] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, fmt.Sprintf("<%s>", link.URL))
|
||||
return nil
|
||||
},
|
||||
help: fmt.Sprintf("Returns the link for %s", alias),
|
||||
}
|
||||
links = append(links, fmt.Sprintf("%s -> %s", alias, link.URL))
|
||||
}
|
||||
}
|
||||
|
||||
commands["links"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return true
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
sendMessage(cmd.session, cmd.message.ChannelID, strings.Join(links, "\n"))
|
||||
return nil
|
||||
},
|
||||
help: "Get all dynamic links",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.etztech.xyz/go-mcm"
|
||||
"go.etztech.xyz/go-mcm/model/django"
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands["register"] = command{
|
||||
validate: func(cmd commandInit) bool {
|
||||
return len(cmd.message.Member.Roles) == 0
|
||||
},
|
||||
run: func(cmd commandInit) error {
|
||||
args := strings.Fields(cmd.message.Content)
|
||||
if len(args) < 2 {
|
||||
return errors.New("you must give this command your application username")
|
||||
}
|
||||
|
||||
sendTyping(cmd.session, cmd.message.ChannelID)
|
||||
|
||||
manager := mcm.NewMCM(cmd.config.MCMToken, cmd.config.MCMURL)
|
||||
models := manager.NewModel()
|
||||
|
||||
apps, err := models.Application(models.NewDjangoBuilder().IExact(django.ApplicationUsername, args[1]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(apps) == 0 {
|
||||
return errors.New("no application found with that username")
|
||||
}
|
||||
|
||||
if !apps[0].Accepted {
|
||||
return errors.New("sorry, your application was denied")
|
||||
}
|
||||
|
||||
// Accepted
|
||||
if err := cmd.session.GuildMemberNickname(cmd.message.GuildID, cmd.message.Author.ID, apps[0].Username); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.session.GuildMemberRoleAdd(cmd.message.GuildID, cmd.message.Author.ID, cmd.config.RegisterRole); err != nil {
|
||||
return err
|
||||
}
|
||||
sendMessage(cmd.session, cmd.config.RegisteredChannel, fmt.Sprintf("Welcome, **%s**!", cmd.message.Author.Mention()))
|
||||
return nil
|
||||
},
|
||||
help: "Register yourself with the Discord",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
module go.etztech.xyz/sedbot
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/bwmarrin/discordgo v0.20.3
|
||||
github.com/urfave/cli/v2 v2.2.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.4
|
||||
go.etztech.xyz/go-mcm v1.2.0
|
||||
go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359
|
||||
go.jolheiser.com/beaver v1.0.2
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
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.20.3 h1:AxjcHGbyBFSC0a3Zx5nDQwbOjU7xai5dXjRnZ0YB7nU=
|
||||
github.com/bwmarrin/discordgo v0.20.3/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
|
||||
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
|
||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etztech.xyz/go-mcm v1.2.0 h1:QEOv6oAjy9ICP3AOcwItNT88wBjOZHK7UKseZEcZh0k=
|
||||
go.etztech.xyz/go-mcm v1.2.0/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc=
|
||||
go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4=
|
||||
go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359/go.mod h1:+fC1WzJm/oS4UEgqr1jPouWerxBys52lTTDA94/5bf8=
|
||||
go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk=
|
||||
go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,61 @@
|
|||
//go:generate go run sedbot.example.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"go.etztech.xyz/sedbot/config"
|
||||
"go.etztech.xyz/sedbot/database"
|
||||
"go.etztech.xyz/sedbot/discord"
|
||||
|
||||
"go.jolheiser.com/beaver"
|
||||
)
|
||||
|
||||
var configFlag string
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&configFlag, "config", "sedbot.toml", "Set config path")
|
||||
flag.Parse()
|
||||
|
||||
beaver.Console.Format = beaver.FormatOptions{
|
||||
TimePrefix: true,
|
||||
StackPrefix: true,
|
||||
StackLimit: 15,
|
||||
LevelPrefix: true,
|
||||
LevelColor: true,
|
||||
}
|
||||
|
||||
cfg, err := config.Load(configFlag)
|
||||
if err != nil {
|
||||
beaver.Fatalf("could not load config: %v", err)
|
||||
}
|
||||
|
||||
db, err := database.Load(cfg.DBPath)
|
||||
if err != nil {
|
||||
beaver.Fatalf("could not load database: %v", err)
|
||||
}
|
||||
|
||||
bot, err := discord.Bot(cfg, db)
|
||||
if err != nil {
|
||||
beaver.Fatalf("could not start Discord bot: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := bot.Open(); err != nil {
|
||||
beaver.Errorf("error running Discord bot: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
beaver.Info("Bot is now running. Press CTRL-C to exit.")
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
|
||||
<-sc
|
||||
|
||||
if err := bot.Close(); err != nil {
|
||||
beaver.Errorf("error closing Discord bot: %v", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
exampleFile = "sedbot.example.toml"
|
||||
writeFile = "config/config_default.go"
|
||||
tmpl = `package config
|
||||
|
||||
func init() {
|
||||
defaultConfig = []byte(` + "`" + `%s` + "`" + `)
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
func main() {
|
||||
bytes, err := ioutil.ReadFile(exampleFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Could not read from %s. Are you in the root directory of the project?", exampleFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
data := fmt.Sprintf(tmpl, string(bytes))
|
||||
|
||||
if err := ioutil.WriteFile(writeFile, []byte(data), os.ModePerm); err != nil {
|
||||
fmt.Printf("Could not write to %s.", writeFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
# token is the Discord token for the bot
|
||||
token = ""
|
||||
|
||||
# prefix is the bot command prefix
|
||||
prefix = "!"
|
||||
|
||||
# mcm_token is the token for the MCM API
|
||||
mcm_token = ""
|
||||
|
||||
# mcm_url is the base URL to MCM
|
||||
mcm_url = ""
|
||||
|
||||
# db_path is the path to the database (default is next to binary)
|
||||
db_path = "sedbot.db"
|
||||
|
||||
# fired_role is to check how many time Carolyn has been fired
|
||||
fired_role = "0"
|
||||
|
||||
# register_role is the role to assign to a user after registering
|
||||
register_role = "0"
|
||||
|
||||
# registered_channel is the channel to message to welcome the newly registered user
|
||||
registered_channel = "0"
|
||||
|
||||
# staff_roles are for staff commands
|
||||
staff_roles = []
|
||||
|
||||
# links are any basic link -> URL commands
|
||||
[[links]]
|
||||
name = "discord"
|
||||
aliases = ["invite", "gib"]
|
||||
url = "https://birbmc.com/discord"
|
||||
|
||||
# message_roles are for messages that should toggle a role when a user selects it
|
||||
[[message_roles]]
|
||||
message_id = "0"
|
||||
role_id = "0"
|
||||
emoji = "thumbsup"
|
Loading…
Reference in New Issue