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