From beb2b4a6aa751bcdfbd39544ab1a6e1bd0788616 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Mon, 22 Feb 2021 19:27:49 +0100 Subject: [PATCH] Add ServerAPI, clean up help, Twitter (#31) Update make commands Remove unnecessary generate step Update Drone to Go 1.16 Add ServerAPI, clean up help, Twitter Signed-off-by: Etzelia Co-authored-by: Etzelia Reviewed-on: https://git.etztech.xyz/Etzelia/sedbot/pulls/31 Co-Authored-By: Etzelia Co-Committed-By: Etzelia --- .drone.yml | 10 +-- .gitignore | 6 +- Makefile | 7 -- config/config.go | 14 +++- .../sedbot.example.toml | 18 ++++++ database/database.go | 27 +------- database/ping.go | 30 +++++++++ database/unban.go | 49 ++++++++++++++ discord/ban.go | 53 +++++++++++++++ discord/broadcast.go | 41 ++++++++++++ discord/discord.go | 49 +++++++++++--- discord/help.go | 64 +++++++++++++++---- discord/tweet.go | 34 ++++++++++ discord/unban.go | 40 ++++++++++++ discord/unbans.go | 35 ++++++++++ discord/utils.go | 43 +++++++++++++ go.mod | 5 +- go.sum | 24 +++++-- main.go | 2 - sedbot.example.go | 35 ---------- 20 files changed, 478 insertions(+), 108 deletions(-) rename sedbot.example.toml => config/sedbot.example.toml (85%) create mode 100644 database/ping.go create mode 100644 database/unban.go create mode 100644 discord/ban.go create mode 100644 discord/broadcast.go create mode 100644 discord/tweet.go create mode 100644 discord/unban.go create mode 100644 discord/unbans.go delete mode 100644 sedbot.example.go diff --git a/.drone.yml b/.drone.yml index 91eafe9..401caf9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,13 +7,13 @@ trigger: steps: - name: build pull: always - image: golang:1.15 + image: golang:1.16 commands: - make test - - make build-all + - make build - name: check pull: always - image: golang:1.15 + image: golang:1.16 commands: - make vet @@ -28,9 +28,9 @@ trigger: steps: - name: build pull: always - image: golang:1.15 + image: golang:1.16 commands: - - make build-all + - make build - name: gitea-release pull: always image: jolheiser/drone-gitea-main:latest diff --git a/.gitignore b/.gitignore index 0e03ca1..e1c8229 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ # GoLand .idea/ -# Generated -config/config_default.go - # sedbot -sedbot* \ No newline at end of file +sedbot* +!config/sedbot.example.toml \ No newline at end of file diff --git a/Makefile b/Makefile index 970187d..339839a 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,6 @@ fmt: imp: imp -w -.PHONY: generate -generate: - $(GO) generate ./... - .PHONY: test test: $(GO) test -race ./... @@ -24,8 +20,5 @@ vet: build: $(GO) build -.PHONY: build-all -build-all: generate build - .PHONY: check check: generate imp fmt test vet build \ No newline at end of file diff --git a/config/config.go b/config/config.go index ce83a62..a1bd19e 100644 --- a/config/config.go +++ b/config/config.go @@ -1,13 +1,15 @@ package config import ( + _ "embed" "io/ioutil" "os" "github.com/pelletier/go-toml" ) -var defaultConfig = []byte("") +//go:embed sedbot.example.toml +var defaultConfig []byte type Config struct { Token string `toml:"token"` @@ -23,6 +25,16 @@ type Config struct { DBPath string `toml:"db_path"` MCPath string `toml:"mc_path"` ImgurClientID string `toml:"imgur_client_id"` + ServerAPI struct { + Endpoint string `toml:"endpoint"` + Token string `toml:"token"` + } `toml:"serverapi"` + Twitter struct { + ConsumerKey string `toml:"consumer_key"` + ConsumerSecret string `toml:"consumer_secret"` + AccessToken string `toml:"access_token"` + AccessSecret string `toml:"access_secret"` + } `toml:"twitter"` StaffRoles []string `toml:"staff_roles"` Echoes []Echo `toml:"echoes"` diff --git a/sedbot.example.toml b/config/sedbot.example.toml similarity index 85% rename from sedbot.example.toml rename to config/sedbot.example.toml index f6d4d2b..4af6fcc 100644 --- a/sedbot.example.toml +++ b/config/sedbot.example.toml @@ -31,6 +31,24 @@ meme_rate = "0" # Imgur Client ID imgur_client_id = "" +# ServerAPI options +[serverapi] +# API endpoint +endpoint = "" +# Auth token +token = "" + +# Twitter options +[twitter] +# Consumer Key +consumer_key = "" +# Consumer Secret +consumer_secret = "" +# Access Token +access_token = "" +# Access Secret +access_secret = "" + # Server options [server] # connection address diff --git a/database/database.go b/database/database.go index 8f3c9ac..663312e 100644 --- a/database/database.go +++ b/database/database.go @@ -1,16 +1,16 @@ package database import ( - "strconv" - "go.etcd.io/bbolt" ) var ( firedBucket = []byte("fired") + unbanBucket = []byte("unban") buckets = [][]byte{ firedBucket, + unbanBucket, } ) @@ -35,26 +35,3 @@ func Load(dbPath string) (*Database, error) { 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))) - }) -} diff --git a/database/ping.go b/database/ping.go new file mode 100644 index 0000000..7f0738d --- /dev/null +++ b/database/ping.go @@ -0,0 +1,30 @@ +package database + +import ( + "strconv" + + "go.etcd.io/bbolt" +) + +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))) + }) +} diff --git a/database/unban.go b/database/unban.go new file mode 100644 index 0000000..ce7c205 --- /dev/null +++ b/database/unban.go @@ -0,0 +1,49 @@ +package database + +import ( + "strconv" + "time" + + "go.etcd.io/bbolt" +) + +type UnbanRecord struct { + Username string + Expiration time.Time +} + +func (u UnbanRecord) ExpirationString() string { + return u.Expiration.Format("01/02/2006 at 03:04:05 pm MST") +} + +func (db *Database) ListUnbans() []UnbanRecord { + unbans := make([]UnbanRecord, 0) + _ = db.db.View(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).ForEach(func(username, unix []byte) error { + unixNum, err := strconv.ParseInt(string(unix), 10, 64) + if err != nil { + return err + } + unbans = append(unbans, UnbanRecord{ + Username: string(username), + Expiration: time.Unix(unixNum, 0), + }) + return nil + }) + }) + return unbans +} + +func (db *Database) AddUnban(record UnbanRecord) error { + usernameByte := []byte(record.Username) + return db.db.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).Put(usernameByte, []byte(strconv.FormatInt(record.Expiration.Unix(), 10))) + }) +} + +func (db *Database) RemoveUnban(username string) error { + usernameByte := []byte(username) + return db.db.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(unbanBucket).Delete(usernameByte) + }) +} diff --git a/discord/ban.go b/discord/ban.go new file mode 100644 index 0000000..de427ac --- /dev/null +++ b/discord/ban.go @@ -0,0 +1,53 @@ +package discord + +import ( + "fmt" + "net/http" + "strings" + "time" + + "go.etztech.xyz/go-serverapi" +) + +func init() { + commands["ban"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires an in-game username.", nil + } + target := args[1] + reason := "You have been banned. Appeal at https://birbmc.com/appeal" + if len(args) >= 3 { + reason = fmt.Sprintf("%s. Appeal at https://birbmc.com/appeal", strings.Join(args[2:], " ")) + } + + ban := serverapi.Ban{ + Kick: serverapi.Kick{ + Unban: serverapi.Unban{ + Target: target, + }, + Reason: reason, + }, + Source: "Discord", + Created: time.Now().Unix(), + } + + status, err := cmd.sapiClient.Ban(ban) + if err != nil { + return "", err + } + if status != http.StatusOK { + return fmt.Sprintf("ServerAPI returned status %d when trying to ban %s", status, target), nil + } + + return fmt.Sprintf("%s was banned by %s", target, cmd.message.Author.Username), nil + }, + help: "Ban a player", + } +} diff --git a/discord/broadcast.go b/discord/broadcast.go new file mode 100644 index 0000000..6b69c17 --- /dev/null +++ b/discord/broadcast.go @@ -0,0 +1,41 @@ +package discord + +import ( + "fmt" + "net/http" + "strings" + + "go.etztech.xyz/go-serverapi" +) + +func init() { + commands["broadcast"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires a message to broadcast", nil + } + + message := strings.Join(args[1:], " ") + broadcast := serverapi.Broadcast{ + From: cmd.message.Author.Username, + Message: message, + } + status, err := cmd.sapiClient.Broadcast(broadcast) + if err != nil { + return "", err + } + if status != http.StatusOK { + return fmt.Sprintf("ServerAPI returned status %d when trying to broadcast.", status), nil + } + + return "Broadcast sent!", nil + }, + help: "Send an in-game broadcast", + } +} diff --git a/discord/discord.go b/discord/discord.go index 07c413e..33c96b8 100644 --- a/discord/discord.go +++ b/discord/discord.go @@ -10,6 +10,9 @@ import ( "go.etztech.xyz/sedbot/imgur" "github.com/bwmarrin/discordgo" + "github.com/dghubble/go-twitter/twitter" + "github.com/dghubble/oauth1" + "go.etztech.xyz/go-serverapi" "go.jolheiser.com/beaver" ) @@ -22,13 +25,17 @@ var ( ) type commandInit struct { - session *discordgo.Session - message *discordgo.Message - config *config.Config - database *database.Database + session *discordgo.Session + message *discordgo.Message + config *config.Config + database *database.Database + sapiClient *serverapi.Client + twitterClient *twitter.Client } type command struct { + staffOnly bool + // TODO Does this really need to exist separately? validate func(cmd commandInit) bool run func(cmd commandInit) (string, error) help string @@ -46,6 +53,22 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) return nil, err } + // Init ServerAPI + sapi := serverapi.NewClient(cfg.ServerAPI.Endpoint, serverapi.WithToken(cfg.ServerAPI.Token)) + + // Init Twitter + twitterConfig := oauth1.NewConfig(cfg.Twitter.ConsumerKey, cfg.Twitter.ConsumerSecret) + twitterToken := oauth1.NewToken(cfg.Twitter.AccessToken, cfg.Twitter.AccessSecret) + twitterHttpClient := twitterConfig.Client(oauth1.NoContext, twitterToken) + twitterClient := twitter.NewClient(twitterHttpClient) + + // Init Unban Schedule + sched := &unbanSchedule{ + db: db, + sapi: sapi, + } + go sched.Run() + for _, messageRole := range cfg.MessageRoles { if messageRoleMap[messageRole.MessageID] == nil { messageRoleMap[messageRole.MessageID] = make(map[string]string) @@ -57,7 +80,7 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error) Echo(cfg) bot.AddHandler(readyHandler()) bot.AddHandler(leaveHandler(cfg)) - bot.AddHandler(commandHandler(cfg, db)) + bot.AddHandler(commandHandler(cfg, db, sapi, twitterClient)) bot.AddHandler(messageHandler(cfg, db)) bot.AddHandler(reactionAddHandler()) bot.AddHandler(reactionRemoveHandler()) @@ -125,7 +148,7 @@ func readyHandler() func(s *discordgo.Session, m *discordgo.Ready) { } } -func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo.Session, m *discordgo.MessageCreate) { +func commandHandler(cfg *config.Config, db *database.Database, sapi *serverapi.Client, twitterClient *twitter.Client) func(s *discordgo.Session, m *discordgo.MessageCreate) { return func(s *discordgo.Session, m *discordgo.MessageCreate) { // Ignore bots if m.Author.Bot { @@ -150,11 +173,17 @@ func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo return } + if cmd.staffOnly && !isStaff(m.Member.Roles, cfg.StaffRoles) { + return + } + cmdInit := commandInit{ - session: s, - message: m.Message, - config: cfg, - database: db, + session: s, + message: m.Message, + config: cfg, + database: db, + sapiClient: sapi, + twitterClient: twitterClient, } if !cmd.validate(cmdInit) { sendMessage(s, m.ChannelID, "You cannot run this command.", false) diff --git a/discord/help.go b/discord/help.go index cc7170a..3d80eb8 100644 --- a/discord/help.go +++ b/discord/help.go @@ -1,8 +1,9 @@ package discord import ( - "fmt" "strings" + + "github.com/bwmarrin/discordgo" ) func init() { @@ -13,29 +14,64 @@ func init() { run: func(cmd commandInit) (string, error) { args := strings.Fields(cmd.message.Content)[1:] - var resp string + var resp *discordgo.MessageEmbed if len(args) == 1 { - resp = singleHelp(args[0]) + resp = singleHelp(cmd, args[0]) } else { - resp = allHelp() + resp = allHelp(cmd) } - return resp, nil + + channel, err := cmd.session.UserChannelCreate(cmd.message.Author.ID) + if err != nil { + return "", err + } + + sendEmbed(cmd.session, channel.ID, 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) +func singleHelp(cmd commandInit, arg string) *discordgo.MessageEmbed { + embed := &discordgo.MessageEmbed{ + Title: "Unkown Command", } - return "Unknown command" + c, ok := commands[arg] + if !ok { + return embed + } + + if c.staffOnly && !isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) { + return embed + } + + embed.Title = arg + embed.Description = c.help + return embed } -func allHelp() string { - helps := make([]string, 0) - for n, c := range commands { - helps = append(helps, fmt.Sprintf("%s: %s", n, c.help)) +func allHelp(cmd commandInit) *discordgo.MessageEmbed { + staff := isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + embed := &discordgo.MessageEmbed{ + Title: "SedBot Help", + Fields: make([]*discordgo.MessageEmbedField, 0), } - return strings.Join(helps, "\n") + if staff { + embed.Description = "Commands with an asterisk (*) are staff-only" + } + for n, c := range commands { + cmdName := n + if c.staffOnly { + cmdName += "*" + } + if !c.staffOnly || staff { + embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{ + Name: cmdName, + Value: c.help, + Inline: true, + }) + } + } + return embed } diff --git a/discord/tweet.go b/discord/tweet.go new file mode 100644 index 0000000..32b9269 --- /dev/null +++ b/discord/tweet.go @@ -0,0 +1,34 @@ +package discord + +import ( + "fmt" + "strings" +) + +func init() { + commands["tweet"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 2 { + return "This command requires a message to tweet", nil + } + + message := strings.Join(args[1:], " ") + tweet, resp, err := cmd.twitterClient.Statuses.Update(message, nil) + if err != nil { + return "", err + } + if resp.StatusCode%100 != 2 { + + } + + return fmt.Sprintf("https://twitter.com/%d/status/%d", tweet.User.ID, tweet.ID), nil + }, + help: "Send a tweet from the BirbMC Twitter", + } +} diff --git a/discord/unban.go b/discord/unban.go new file mode 100644 index 0000000..324b90c --- /dev/null +++ b/discord/unban.go @@ -0,0 +1,40 @@ +package discord + +import ( + "fmt" + "strconv" + "strings" + "time" + + "go.etztech.xyz/sedbot/database" +) + +func init() { + commands["unban"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + args := strings.Fields(cmd.message.Content) + + if len(args) < 3 { + return "This command requires an in-game username and number of days (use 0 days to unban on next schedule).", nil + } + days, err := strconv.Atoi(args[2]) + if err != nil { + return "number of days must be an integer", nil + } + target := args[1] + expiration := time.Now().Add(time.Hour * 24 * time.Duration(days)) + record := database.UnbanRecord{ + Username: target, + Expiration: expiration, + } + + return fmt.Sprintf("%s will be unbanned on %s", target, record.ExpirationString()), + cmd.database.AddUnban(record) + }, + help: "Unban a player", + } +} diff --git a/discord/unbans.go b/discord/unbans.go new file mode 100644 index 0000000..698ab60 --- /dev/null +++ b/discord/unbans.go @@ -0,0 +1,35 @@ +package discord + +import ( + "github.com/bwmarrin/discordgo" +) + +func init() { + commands["unbans"] = command{ + staffOnly: true, + validate: func(cmd commandInit) bool { + return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) + }, + run: func(cmd commandInit) (string, error) { + unbans := cmd.database.ListUnbans() + if len(unbans) == 0 { + return "There are no pending unbans", nil + } + + embed := &discordgo.MessageEmbed{ + Fields: make([]*discordgo.MessageEmbedField, len(unbans)), + } + for i, record := range cmd.database.ListUnbans() { + embed.Fields[i] = &discordgo.MessageEmbedField{ + Name: record.Username, + Value: record.ExpirationString(), + Inline: true, + } + } + + sendEmbed(cmd.session, cmd.message.ChannelID, embed) + return "", nil + }, + help: "Unban a player", + } +} diff --git a/discord/utils.go b/discord/utils.go index 7406bbb..22b60cc 100644 --- a/discord/utils.go +++ b/discord/utils.go @@ -2,7 +2,13 @@ package discord import ( r "math/rand" + "net/http" "time" + + "go.etztech.xyz/sedbot/database" + + "go.etztech.xyz/go-serverapi" + "go.jolheiser.com/beaver" ) type rateLimit struct { @@ -38,3 +44,40 @@ func random(list []string) string { idx := rand.Intn(size) return list[idx] } + +type unbanSchedule struct { + db *database.Database + sapi *serverapi.Client +} + +func (u *unbanSchedule) Run() { + u.check() + ticker := time.NewTicker(time.Minute * 5) + for { + <-ticker.C + u.check() + } +} + +func (u *unbanSchedule) check() { + beaver.Debug("Running unban schedule") + now := time.Now() + for _, record := range u.db.ListUnbans() { + if now.After(record.Expiration) { + beaver.Infof("Unbanning %s", record.Username) + unban := serverapi.Unban{ + Target: record.Username, + } + status, err := u.sapi.Unban(unban) + if err != nil { + beaver.Error(err) + } + if status != http.StatusOK { + beaver.Errorf("ServerAPI returned status %d when trying to ban %s", status, record.Username) + } + if err := u.db.RemoveUnban(record.Username); err != nil { + beaver.Errorf("could not remove unban for %s in database", record.Username) + } + } + } +} diff --git a/go.mod b/go.mod index 3ee8ad2..f90ef43 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,17 @@ module go.etztech.xyz/sedbot -go 1.14 +go 1.16 require ( github.com/bwmarrin/discordgo v0.22.0 + github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d + github.com/dghubble/oauth1 v0.7.0 github.com/gorilla/websocket v1.4.2 // indirect github.com/pelletier/go-toml v1.8.1 go.etcd.io/bbolt v1.3.4 go.etztech.xyz/falseknees v0.0.1 go.etztech.xyz/go-mcm v1.3.1 + go.etztech.xyz/go-serverapi v0.0.3 go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359 go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/gojang v0.0.3 diff --git a/go.sum b/go.sum index 4f5c3cb..7ba0f54 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,46 @@ github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM= github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= +github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d h1:sBKr0A8iQ1qAOozedZ8Aox+Jpv+TeP1Qv7dcQyW8V+M= +github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE= +github.com/dghubble/oauth1 v0.7.0 h1:AlpZdbRiJM4XGHIlQ8BuJ/wlpGwFEJNnB4Mc+78tA/w= +github.com/dghubble/oauth1 v0.7.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk= +github.com/dghubble/sling v1.3.0 h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU= +github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 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/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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/falseknees v0.0.1 h1:XjlBqMyBUH5b7e/9oedEwZ9pnz3sqMhXQv6vnQocxeM= go.etztech.xyz/falseknees v0.0.1/go.mod h1:Acn1AwrvAArQEqhMBDlak5BvCZ3jgV8vdL8Pe5ZldRE= go.etztech.xyz/go-mcm v1.3.1 h1:RLdOQrMgw0eP7bsfRRbXLW8c5/RaJ5Mg7i/ESFaUwvY= go.etztech.xyz/go-mcm v1.3.1/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc= +go.etztech.xyz/go-serverapi v0.0.3 h1:h2Zww0x5E61cH4jXB97x3oUnbryEuLkuq+RTgIi5/U4= +go.etztech.xyz/go-serverapi v0.0.3/go.mod h1:tq4J5zxVnAwzOiv79iLUzpfNAd7IoNirOfb0gt3/IEY= 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= go.jolheiser.com/gojang v0.0.3 h1:EWDLMo6X3f67DK2p/mSB680H43t8SDrDYNZnXvY7PLg= go.jolheiser.com/gojang v0.0.3/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I= +go.jolheiser.com/gql v0.0.1 h1:y3LGHcJUZI9otTCcMn8TVdF3aEzNX0FW6m0YUamlLto= +go.jolheiser.com/gql v0.0.1/go.mod h1:74eYqVRIxsOFxtVl0RYGKNyYQgJYQaxOCgar7LP71Hw= go.jolheiser.com/xkcd v0.0.1 h1:pRNY2BXxUS+NMtKlm/ENumOr7g3k4VWY/QoDri9YSNU= go.jolheiser.com/xkcd v0.0.1/go.mod h1:AzWPrZToCLfpazsZBkeu/nPuIvurMqfCOptiydz7Dvk= -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/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= @@ -30,9 +48,7 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -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= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go index 442ec31..9be634f 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,3 @@ -//go:generate go run sedbot.example.go - package main import ( diff --git a/sedbot.example.go b/sedbot.example.go deleted file mode 100644 index 10abce6..0000000 --- a/sedbot.example.go +++ /dev/null @@ -1,35 +0,0 @@ -// +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) - } -}