forked from Minecraft/canopeas
Merge branch 'broom' of birbmc.com:Etzelia/sedbot into main
# Conflicts: # .drone.ymldiscord-sync
commit
326b370ca8
14
.drone.yml
14
.drone.yml
|
@ -7,13 +7,13 @@ trigger:
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.15
|
image: golang:1.16
|
||||||
commands:
|
commands:
|
||||||
- make test
|
- make test
|
||||||
- make build-all
|
- make build
|
||||||
- name: check
|
- name: check
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.15
|
image: golang:1.16
|
||||||
commands:
|
commands:
|
||||||
- make vet
|
- make vet
|
||||||
|
|
||||||
|
@ -24,19 +24,19 @@ trigger:
|
||||||
event:
|
event:
|
||||||
- push
|
- push
|
||||||
branch:
|
branch:
|
||||||
- master
|
- main
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.15
|
image: golang:1.16
|
||||||
commands:
|
commands:
|
||||||
- make build-all
|
- make build
|
||||||
- name: gitea-release
|
- name: gitea-release
|
||||||
pull: always
|
pull: always
|
||||||
image: jolheiser/drone-gitea-main:latest
|
image: jolheiser/drone-gitea-main:latest
|
||||||
settings:
|
settings:
|
||||||
token:
|
token:
|
||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
base_url: https://git.etztech.xyz
|
base: https://git.etztech.xyz
|
||||||
files:
|
files:
|
||||||
- "sedbot"
|
- "sedbot"
|
|
@ -1,8 +1,6 @@
|
||||||
# GoLand
|
# GoLand
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# Generated
|
|
||||||
config/config_default.go
|
|
||||||
|
|
||||||
# sedbot
|
# sedbot
|
||||||
sedbot*
|
sedbot*
|
||||||
|
!config/sedbot.example.toml
|
7
Makefile
7
Makefile
|
@ -8,10 +8,6 @@ fmt:
|
||||||
imp:
|
imp:
|
||||||
imp -w
|
imp -w
|
||||||
|
|
||||||
.PHONY: generate
|
|
||||||
generate:
|
|
||||||
$(GO) generate ./...
|
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
$(GO) test -race ./...
|
$(GO) test -race ./...
|
||||||
|
@ -24,8 +20,5 @@ vet:
|
||||||
build:
|
build:
|
||||||
$(GO) build
|
$(GO) build
|
||||||
|
|
||||||
.PHONY: build-all
|
|
||||||
build-all: generate build
|
|
||||||
|
|
||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: generate imp fmt test vet build
|
check: generate imp fmt test vet build
|
|
@ -1,13 +1,15 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/pelletier/go-toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultConfig = []byte("")
|
//go:embed sedbot.example.toml
|
||||||
|
var defaultConfig []byte
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Token string `toml:"token"`
|
Token string `toml:"token"`
|
||||||
|
@ -22,12 +24,24 @@ type Config struct {
|
||||||
} `toml:"server"`
|
} `toml:"server"`
|
||||||
DBPath string `toml:"db_path"`
|
DBPath string `toml:"db_path"`
|
||||||
MCPath string `toml:"mc_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"`
|
StaffRoles []string `toml:"staff_roles"`
|
||||||
Echoes []Echo `toml:"echoes"`
|
Echoes []Echo `toml:"echoes"`
|
||||||
MessageRoles []MessageRole `toml:"message_roles"`
|
MessageRoles []MessageRole `toml:"message_roles"`
|
||||||
RegisterRole string `toml:"register_role"`
|
RegisterRole string `toml:"register_role"`
|
||||||
RegisteredChannel string `toml:"registered_channel"`
|
RegisteredChannel string `toml:"registered_channel"`
|
||||||
|
LeaveChannel string `toml:"leave_channel"`
|
||||||
FiredRole string `toml:"fired_role"`
|
FiredRole string `toml:"fired_role"`
|
||||||
MemeRate string `toml:"meme_rate"`
|
MemeRate string `toml:"meme_rate"`
|
||||||
Insult struct {
|
Insult struct {
|
||||||
|
@ -76,10 +90,15 @@ func Load(configPath string) (*Config, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg *Config
|
var cfg Config
|
||||||
if err = toml.Unmarshal(configContent, &cfg); err != nil {
|
tree, err := toml.LoadBytes(configContent)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg, nil
|
if err := tree.Unmarshal(&cfg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,36 @@ register_role = "0"
|
||||||
# registered_channel is the channel to message to welcome the newly registered user
|
# registered_channel is the channel to message to welcome the newly registered user
|
||||||
registered_channel = "0"
|
registered_channel = "0"
|
||||||
|
|
||||||
|
# leave_channel is the channel to post leave messages to
|
||||||
|
leave_channel = "0"
|
||||||
|
|
||||||
# staff_roles are for staff commands
|
# staff_roles are for staff commands
|
||||||
staff_roles = []
|
staff_roles = []
|
||||||
|
|
||||||
# meme_rate is the rate limit for memes
|
# meme_rate is the rate limit for memes
|
||||||
meme_rate = "0"
|
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 options
|
||||||
[server]
|
[server]
|
||||||
# connection address
|
# connection address
|
|
@ -1,16 +1,16 @@
|
||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
firedBucket = []byte("fired")
|
firedBucket = []byte("fired")
|
||||||
|
unbanBucket = []byte("unban")
|
||||||
|
|
||||||
buckets = [][]byte{
|
buckets = [][]byte{
|
||||||
firedBucket,
|
firedBucket,
|
||||||
|
unbanBucket,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,26 +35,3 @@ func Load(dbPath string) (*Database, error) {
|
||||||
db: db,
|
db: db,
|
||||||
}, nil
|
}, 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,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)))
|
||||||
|
})
|
||||||
|
}
|
|
@ -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)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.etztech.xyz/go-serverapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
staffOnly: true,
|
||||||
|
name: "ban",
|
||||||
|
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",
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.etztech.xyz/falseknees"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
name: "birb",
|
||||||
|
validate: func(cmd commandInit) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
run: func(cmd commandInit) (string, error) {
|
||||||
|
if !memeRateLimit.Try() {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client := falseknees.New()
|
||||||
|
|
||||||
|
var comic *falseknees.Comic
|
||||||
|
var err error
|
||||||
|
args := strings.Fields(cmd.message.Content)
|
||||||
|
if len(args) < 2 {
|
||||||
|
comic, err = client.Random(context.Background())
|
||||||
|
} else if strings.EqualFold(args[1], "new") {
|
||||||
|
comic, err = client.Current(context.Background())
|
||||||
|
} else {
|
||||||
|
comicNum, err := strconv.Atoi(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
comic, err = client.Comic(context.Background(), comicNum)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d: %s\n%s", comic.Num, comic.Title, comic.Img), nil
|
||||||
|
},
|
||||||
|
help: "Get a FalseKnees comic",
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.etztech.xyz/go-serverapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
staffOnly: true,
|
||||||
|
name: "broadcast",
|
||||||
|
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",
|
||||||
|
})
|
||||||
|
}
|
|
@ -8,7 +8,8 @@ import (
|
||||||
const clearMax = 20
|
const clearMax = 20
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["clear"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "clear",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
||||||
},
|
},
|
||||||
|
@ -24,7 +25,7 @@ func init() {
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
limitArg = 2
|
limitArg = 2
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return "This command takes needs two arguments with a mention", nil
|
return "This command takes two arguments with a mention", nil
|
||||||
}
|
}
|
||||||
} else if len(args) < 1 {
|
} else if len(args) < 1 {
|
||||||
return "This command takes one argument without a mention", nil
|
return "This command takes one argument without a mention", nil
|
||||||
|
@ -64,5 +65,5 @@ func init() {
|
||||||
return "", cmd.session.ChannelMessagesBulkDelete(cmd.message.ChannelID, batch)
|
return "", cmd.session.ChannelMessagesBulkDelete(cmd.message.ChannelID, batch)
|
||||||
},
|
},
|
||||||
help: "Clear messages",
|
help: "Clear messages",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["compliment"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "compliment",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -38,5 +39,5 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Compliment someone!",
|
help: "Compliment someone!",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ type dadJoke struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["dad"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "dad",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -60,5 +61,5 @@ func init() {
|
||||||
return dj.Joke, nil
|
return dj.Joke, nil
|
||||||
},
|
},
|
||||||
help: "Get a random Dad joke",
|
help: "Get a random Dad joke",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,29 @@
|
||||||
package discord
|
package discord
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.etztech.xyz/sedbot/config"
|
"go.etztech.xyz/sedbot/config"
|
||||||
"go.etztech.xyz/sedbot/database"
|
"go.etztech.xyz/sedbot/database"
|
||||||
|
"go.etztech.xyz/sedbot/imgur"
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/dghubble/go-twitter/twitter"
|
||||||
|
"github.com/dghubble/oauth1"
|
||||||
|
"go.etztech.xyz/go-serverapi"
|
||||||
"go.jolheiser.com/beaver"
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register commands to this map
|
// Register commands to this map
|
||||||
var (
|
var (
|
||||||
commands = make(map[string]command)
|
commands = make([]*command, 0)
|
||||||
|
commandMap = make(map[string]*command)
|
||||||
messageRoleMap = make(map[string]map[string]string)
|
messageRoleMap = make(map[string]map[string]string)
|
||||||
|
|
||||||
memeRateLimit *rateLimit
|
memeRateLimit *rateLimit
|
||||||
|
embedColor = 0x007D96
|
||||||
)
|
)
|
||||||
|
|
||||||
type commandInit struct {
|
type commandInit struct {
|
||||||
|
@ -24,11 +31,19 @@ type commandInit struct {
|
||||||
message *discordgo.Message
|
message *discordgo.Message
|
||||||
config *config.Config
|
config *config.Config
|
||||||
database *database.Database
|
database *database.Database
|
||||||
|
sapiClient *serverapi.Client
|
||||||
|
twitterClient *twitter.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type command struct {
|
type command struct {
|
||||||
|
staffOnly bool
|
||||||
|
deleteInvocation bool
|
||||||
|
echo bool
|
||||||
|
// TODO Does this really need to exist separately?
|
||||||
validate func(cmd commandInit) bool
|
validate func(cmd commandInit) bool
|
||||||
run func(cmd commandInit) (string, error)
|
run func(cmd commandInit) (string, error)
|
||||||
|
name string
|
||||||
|
aliases []string
|
||||||
help string
|
help string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +53,28 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init Jupiter images
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
if err := imgur.Init(cfg.ImgurClientID); err != nil {
|
||||||
|
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 {
|
for _, messageRole := range cfg.MessageRoles {
|
||||||
if messageRoleMap[messageRole.MessageID] == nil {
|
if messageRoleMap[messageRole.MessageID] == nil {
|
||||||
messageRoleMap[messageRole.MessageID] = make(map[string]string)
|
messageRoleMap[messageRole.MessageID] = make(map[string]string)
|
||||||
|
@ -46,9 +83,22 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error)
|
||||||
messageRoleMap[messageRole.MessageID][messageRole.Emoji] = messageRole.RoleID
|
messageRoleMap[messageRole.MessageID][messageRole.Emoji] = messageRole.RoleID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init commandMap
|
||||||
Echo(cfg)
|
Echo(cfg)
|
||||||
|
for _, c := range commands {
|
||||||
|
if c.name == "" {
|
||||||
|
beaver.Errorf("command is missing a name: %s", c.help)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
commandMap[c.name] = c
|
||||||
|
for _, a := range c.aliases {
|
||||||
|
commandMap[a] = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bot.AddHandler(readyHandler())
|
bot.AddHandler(readyHandler())
|
||||||
bot.AddHandler(commandHandler(cfg, db))
|
bot.AddHandler(leaveHandler(cfg))
|
||||||
|
bot.AddHandler(commandHandler(cfg, db, sapi, twitterClient))
|
||||||
bot.AddHandler(messageHandler(cfg, db))
|
bot.AddHandler(messageHandler(cfg, db))
|
||||||
bot.AddHandler(reactionAddHandler())
|
bot.AddHandler(reactionAddHandler())
|
||||||
bot.AddHandler(reactionRemoveHandler())
|
bot.AddHandler(reactionRemoveHandler())
|
||||||
|
@ -60,6 +110,9 @@ func Bot(cfg *config.Config, db *database.Database) (*discordgo.Session, error)
|
||||||
}
|
}
|
||||||
memeRateLimit = NewRateLimit(d)
|
memeRateLimit = NewRateLimit(d)
|
||||||
|
|
||||||
|
// Intents
|
||||||
|
bot.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAll)
|
||||||
|
|
||||||
return bot, nil
|
return bot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +141,7 @@ func sendMessage(s *discordgo.Session, channelID, content string, scrub bool) *d
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendEmbed(s *discordgo.Session, channelID string, embed *discordgo.MessageEmbed) *discordgo.Message {
|
func sendEmbed(s *discordgo.Session, channelID string, embed *discordgo.MessageEmbed) *discordgo.Message {
|
||||||
|
embed.Color = embedColor
|
||||||
msg, err := s.ChannelMessageSendEmbed(channelID, embed)
|
msg, err := s.ChannelMessageSendEmbed(channelID, embed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beaver.Errorf("could not send embed: %v", err)
|
beaver.Errorf("could not send embed: %v", err)
|
||||||
|
@ -113,7 +167,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) {
|
return func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
// Ignore bots
|
// Ignore bots
|
||||||
if m.Author.Bot {
|
if m.Author.Bot {
|
||||||
|
@ -133,21 +187,32 @@ func commandHandler(cfg *config.Config, db *database.Database) func(s *discordgo
|
||||||
|
|
||||||
cmdArg := strings.ToLower(args[0])
|
cmdArg := strings.ToLower(args[0])
|
||||||
|
|
||||||
cmd, ok := commands[cmdArg]
|
cmd, ok := commandMap[cmdArg]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd.staffOnly && !isStaff(m.Member.Roles, cfg.StaffRoles) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cmdInit := commandInit{
|
cmdInit := commandInit{
|
||||||
session: s,
|
session: s,
|
||||||
message: m.Message,
|
message: m.Message,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
database: db,
|
database: db,
|
||||||
|
sapiClient: sapi,
|
||||||
|
twitterClient: twitterClient,
|
||||||
}
|
}
|
||||||
if !cmd.validate(cmdInit) {
|
if !cmd.validate(cmdInit) {
|
||||||
sendMessage(s, m.ChannelID, "You cannot run this command.", false)
|
sendMessage(s, m.ChannelID, "You cannot run this command.", false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if cmd.deleteInvocation {
|
||||||
|
if err := s.ChannelMessageDelete(m.Message.ChannelID, m.Message.ID); err != nil {
|
||||||
|
beaver.Warnf("could not remove invocation for %s: %v", m.Content, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
feedback, err := cmd.run(cmdInit)
|
feedback, err := cmd.run(cmdInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
feedback = "Internal error"
|
feedback = "Internal error"
|
||||||
|
@ -204,3 +269,9 @@ func reactionHandler(add bool, s *discordgo.Session, m *discordgo.MessageReactio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func leaveHandler(cfg *config.Config) func(s *discordgo.Session, m *discordgo.GuildMemberRemove) {
|
||||||
|
return func(s *discordgo.Session, m *discordgo.GuildMemberRemove) {
|
||||||
|
sendMessage(s, cfg.LeaveChannel, fmt.Sprintf("%s (%s) left the server. :sob:", m.Mention(), m.User.String()), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,44 +5,57 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.etztech.xyz/sedbot/config"
|
"go.etztech.xyz/sedbot/config"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Echo(cfg *config.Config) {
|
func Echo(cfg *config.Config) {
|
||||||
echoes := make([]string, 0)
|
|
||||||
for _, e := range cfg.Echoes {
|
for _, e := range cfg.Echoes {
|
||||||
echo := e
|
commands = append(commands, &command{
|
||||||
commands[echo.Name] = command{
|
name: e.Name,
|
||||||
|
aliases: e.Aliases,
|
||||||
|
echo: true,
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
run: func(cmd commandInit) (string, error) {
|
run: func(cmd commandInit) (string, error) {
|
||||||
return echo.Message, nil
|
return e.Message, nil
|
||||||
},
|
},
|
||||||
help: echo.Help,
|
help: e.Help,
|
||||||
}
|
})
|
||||||
for _, a := range echo.Aliases {
|
|
||||||
alias := a
|
|
||||||
commands[alias] = command{
|
|
||||||
validate: func(cmd commandInit) bool {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
run: func(cmd commandInit) (string, error) {
|
|
||||||
return echo.Message, nil
|
|
||||||
},
|
|
||||||
help: echo.Help,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
combined := append([]string{echo.Name}, echo.Aliases...)
|
|
||||||
echoes = append(echoes, fmt.Sprintf("**%s**: %s", strings.Join(combined, ", "), echo.Help))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
commands["echoes"] = command{
|
commands = append(commands, &command{
|
||||||
|
deleteInvocation: true,
|
||||||
|
name: "echoes",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
run: func(cmd commandInit) (string, error) {
|
run: func(cmd commandInit) (string, error) {
|
||||||
return strings.Join(echoes, "\n"), nil
|
embed := &discordgo.MessageEmbed{
|
||||||
|
Title: "Echo Commands",
|
||||||
|
Fields: make([]*discordgo.MessageEmbedField, len(cfg.Echoes)),
|
||||||
|
}
|
||||||
|
for i, echo := range cfg.Echoes {
|
||||||
|
name := echo.Name
|
||||||
|
if len(echo.Aliases) > 0 {
|
||||||
|
name += fmt.Sprintf(" (%s)", strings.Join(echo.Aliases, ", "))
|
||||||
|
}
|
||||||
|
embed.Fields[i] = &discordgo.MessageEmbedField{
|
||||||
|
Name: name,
|
||||||
|
Value: echo.Help,
|
||||||
|
Inline: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, err := cmd.session.UserChannelCreate(cmd.message.Author.ID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEmbed(cmd.session, channel.ID, embed)
|
||||||
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Get all dynamic messages",
|
help: "Get all dynamic messages",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["fired"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "fired",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -14,5 +15,5 @@ func init() {
|
||||||
cmd.database.CheckPing(cmd.config.FiredRole)), nil
|
cmd.database.CheckPing(cmd.config.FiredRole)), nil
|
||||||
},
|
},
|
||||||
help: "Check how many times Carolyn has been fired.",
|
help: "Check how many times Carolyn has been fired.",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,39 +3,86 @@ package discord
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["help"] = command{
|
commands = append(commands, &command{
|
||||||
|
deleteInvocation: true,
|
||||||
|
name: "help",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
run: func(cmd commandInit) (string, error) {
|
run: func(cmd commandInit) (string, error) {
|
||||||
args := strings.Fields(cmd.message.Content)[1:]
|
args := strings.Fields(cmd.message.Content)[1:]
|
||||||
|
|
||||||
var resp string
|
var resp *discordgo.MessageEmbed
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
resp = singleHelp(args[0])
|
resp = singleHelp(cmd, args[0])
|
||||||
} else {
|
} 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!",
|
help: "HELP! HEEEEEEEEEELP!",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func singleHelp(cmd string) string {
|
func singleHelp(cmd commandInit, arg string) *discordgo.MessageEmbed {
|
||||||
if c, ok := commands[cmd]; ok {
|
embed := &discordgo.MessageEmbed{
|
||||||
return fmt.Sprintf("%s: %s", cmd, c.help)
|
Title: "Unkown Command",
|
||||||
|
Color: 0x007D96,
|
||||||
}
|
}
|
||||||
return "Unknown command"
|
c, ok := commandMap[arg]
|
||||||
|
if !ok {
|
||||||
|
return embed
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.staffOnly && !isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles) {
|
||||||
|
return embed
|
||||||
|
}
|
||||||
|
|
||||||
|
embed.Title = c.name
|
||||||
|
embed.Description = c.help
|
||||||
|
return embed
|
||||||
}
|
}
|
||||||
|
|
||||||
func allHelp() string {
|
func allHelp(cmd commandInit) *discordgo.MessageEmbed {
|
||||||
helps := make([]string, 0)
|
staff := isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
||||||
for n, c := range commands {
|
embed := &discordgo.MessageEmbed{
|
||||||
helps = append(helps, fmt.Sprintf("%s: %s", n, c.help))
|
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 _, c := range commands {
|
||||||
|
if c.echo {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdName := c.name
|
||||||
|
if len(c.aliases) > 0 {
|
||||||
|
cmdName += fmt.Sprintf(" (%s)", strings.Join(c.aliases, ", "))
|
||||||
|
}
|
||||||
|
if c.staffOnly {
|
||||||
|
cmdName = fmt.Sprintf("*%s", cmdName)
|
||||||
|
}
|
||||||
|
if !c.staffOnly || staff {
|
||||||
|
embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{
|
||||||
|
Name: cmdName,
|
||||||
|
Value: c.help,
|
||||||
|
Inline: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return embed
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmd := command{
|
commands = append(commands, &command{
|
||||||
|
name: "history",
|
||||||
|
aliases: []string{"names"},
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -79,8 +81,5 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Minecraft name history",
|
help: "Minecraft name history",
|
||||||
}
|
})
|
||||||
|
|
||||||
commands["history"] = cmd
|
|
||||||
commands["names"] = cmd
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ package discord
|
||||||
import "go.etztech.xyz/inspiro"
|
import "go.etztech.xyz/inspiro"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["inspire"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "inspire",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -22,5 +23,5 @@ func init() {
|
||||||
return img, nil
|
return img, nil
|
||||||
},
|
},
|
||||||
help: "Get inspired!",
|
help: "Get inspired!",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["insult"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "insult",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -39,5 +40,5 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Insult someone!",
|
help: "Insult someone!",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import "go.etztech.xyz/sedbot/imgur"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
name: "jupiter",
|
||||||
|
aliases: []string{"jup", "jupjup"},
|
||||||
|
validate: func(cmd commandInit) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
run: func(cmd commandInit) (string, error) {
|
||||||
|
if !memeRateLimit.Try() {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
img := imgur.Images[rand.Intn(len(imgur.Images))-1]
|
||||||
|
return img.Link, nil
|
||||||
|
},
|
||||||
|
help: "Get a Jupiter image",
|
||||||
|
})
|
||||||
|
}
|
|
@ -16,7 +16,8 @@ import (
|
||||||
const bannedPlayersFile = "banned-players.json"
|
const bannedPlayersFile = "banned-players.json"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["register"] = command{
|
commands = append(commands, &command{
|
||||||
|
name: "register",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return len(cmd.message.Member.Roles) == 0
|
return len(cmd.message.Member.Roles) == 0
|
||||||
},
|
},
|
||||||
|
@ -58,7 +59,7 @@ func init() {
|
||||||
|
|
||||||
nickname = player.Username
|
nickname = player.Username
|
||||||
if len(apps) == 0 {
|
if len(apps) == 0 {
|
||||||
apps, err = models.Application(models.NewDjangoBuilder().Eq(django.ApplicationID, player.ApplicationID))
|
apps, err = models.Application(models.NewDjangoBuilder().Exact(django.ApplicationID, player.ApplicationID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "Something went wrong, please contact staff", nil
|
return "Something went wrong, please contact staff", nil
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,7 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Register yourself with the Discord",
|
help: "Register yourself with the Discord",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ban struct {
|
type Ban struct {
|
||||||
|
|
|
@ -9,7 +9,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cmd := command{
|
commands = append(commands, &command{
|
||||||
|
name: "status",
|
||||||
|
aliases: []string{"version", "online"},
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -22,7 +24,6 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
embed := &discordgo.MessageEmbed{
|
embed := &discordgo.MessageEmbed{
|
||||||
Color: 0x007D96,
|
|
||||||
Title: fmt.Sprintf("Server Status for `%s`", cmd.config.Server.Address),
|
Title: fmt.Sprintf("Server Status for `%s`", cmd.config.Server.Address),
|
||||||
Description: q.MOTD,
|
Description: q.MOTD,
|
||||||
Fields: []*discordgo.MessageEmbedField{
|
Fields: []*discordgo.MessageEmbedField{
|
||||||
|
@ -32,12 +33,12 @@ func init() {
|
||||||
Inline: true,
|
Inline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Player's Online",
|
Name: "~~Players~~ Birbs Online",
|
||||||
Value: fmt.Sprintf("%d / %d", q.CurrentPlayers, q.MaxPlayers),
|
Value: fmt.Sprintf("%d / %d", q.CurrentPlayers, q.MaxPlayers),
|
||||||
Inline: true,
|
Inline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Players",
|
Name: "~~Players~~ Birbs",
|
||||||
Value: strings.Join(q.Players, ", "),
|
Value: strings.Join(q.Players, ", "),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -46,9 +47,5 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Get the server status",
|
help: "Get the server status",
|
||||||
}
|
})
|
||||||
|
|
||||||
commands["status"] = cmd
|
|
||||||
commands["version"] = cmd
|
|
||||||
commands["online"] = cmd
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
staffOnly: true,
|
||||||
|
name: "tweet",
|
||||||
|
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",
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.etztech.xyz/sedbot/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
staffOnly: true,
|
||||||
|
name: "unban",
|
||||||
|
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",
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
staffOnly: true,
|
||||||
|
name: "unbans",
|
||||||
|
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: "Check the unban scheduler",
|
||||||
|
})
|
||||||
|
}
|
|
@ -2,7 +2,13 @@ package discord
|
||||||
|
|
||||||
import (
|
import (
|
||||||
r "math/rand"
|
r "math/rand"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.etztech.xyz/sedbot/database"
|
||||||
|
|
||||||
|
"go.etztech.xyz/go-serverapi"
|
||||||
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rateLimit struct {
|
type rateLimit struct {
|
||||||
|
@ -38,3 +44,40 @@ func random(list []string) string {
|
||||||
idx := rand.Intn(size)
|
idx := rand.Intn(size)
|
||||||
return list[idx]
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,15 +7,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
commands["welcome"] = command{
|
commands = append(commands, &command{
|
||||||
|
deleteInvocation: true,
|
||||||
|
name: "welcome",
|
||||||
validate: func(cmd commandInit) bool {
|
validate: func(cmd commandInit) bool {
|
||||||
return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
return isStaff(cmd.message.Member.Roles, cmd.config.StaffRoles)
|
||||||
},
|
},
|
||||||
run: func(cmd commandInit) (string, error) {
|
run: func(cmd commandInit) (string, error) {
|
||||||
if err := cmd.session.ChannelMessageDelete(cmd.message.ChannelID, cmd.message.ID); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
orphans := make([]*discordgo.Member, 0)
|
orphans := make([]*discordgo.Member, 0)
|
||||||
|
|
||||||
members, err := cmd.session.GuildMembers(cmd.message.GuildID, "", 1000)
|
members, err := cmd.session.GuildMembers(cmd.message.GuildID, "", 1000)
|
||||||
|
@ -49,5 +47,5 @@ func init() {
|
||||||
return "", nil
|
return "", nil
|
||||||
},
|
},
|
||||||
help: "Get a list of people with no roles",
|
help: "Get a list of people with no roles",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"go.jolheiser.com/xkcd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
commands = append(commands, &command{
|
||||||
|
name: "xkcd",
|
||||||
|
validate: func(cmd commandInit) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
run: func(cmd commandInit) (string, error) {
|
||||||
|
if !memeRateLimit.Try() {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client := xkcd.New()
|
||||||
|
|
||||||
|
var comic *xkcd.Comic
|
||||||
|
var err error
|
||||||
|
args := strings.Fields(cmd.message.Content)
|
||||||
|
if len(args) < 2 {
|
||||||
|
comic, err = client.Current(context.Background())
|
||||||
|
} else {
|
||||||
|
comicNum, err := strconv.Atoi(args[1])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
comic, err = client.Comic(context.Background(), comicNum)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%d: %s\n%s\n%s", comic.Num, comic.SafeTitle, comic.Alt, comic.Img), nil
|
||||||
|
},
|
||||||
|
help: "Get an xkcd comic",
|
||||||
|
})
|
||||||
|
}
|
19
go.mod
19
go.mod
|
@ -1,16 +1,21 @@
|
||||||
module go.etztech.xyz/sedbot
|
module go.etztech.xyz/sedbot
|
||||||
|
|
||||||
go 1.14
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/bwmarrin/discordgo v0.22.0
|
||||||
github.com/bwmarrin/discordgo v0.21.1
|
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/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/pelletier/go-toml v1.8.1
|
||||||
go.etcd.io/bbolt v1.3.4
|
go.etcd.io/bbolt v1.3.4
|
||||||
go.etztech.xyz/go-mcm v1.3.0
|
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.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359
|
||||||
go.jolheiser.com/beaver v1.0.2
|
go.jolheiser.com/beaver v1.0.2
|
||||||
go.jolheiser.com/gojang v0.0.2
|
go.jolheiser.com/gojang v0.0.3
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
go.jolheiser.com/xkcd v0.0.1
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 // indirect
|
||||||
)
|
)
|
||||||
|
|
54
go.sum
54
go.sum
|
@ -1,33 +1,55 @@
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
||||||
github.com/bwmarrin/discordgo v0.21.1 h1:UI2PWwzvn5IFuscYcDc6QB/duhs9MUIjQ4HclcIZisc=
|
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
|
||||||
github.com/bwmarrin/discordgo v0.21.1/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
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/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.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
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/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 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etztech.xyz/go-mcm v1.3.0 h1:ULhLEHRJZYh+hIgHfp7IuqpOn6H7kkrVxnnfzyZLQM0=
|
go.etztech.xyz/falseknees v0.0.1 h1:XjlBqMyBUH5b7e/9oedEwZ9pnz3sqMhXQv6vnQocxeM=
|
||||||
go.etztech.xyz/go-mcm v1.3.0/go.mod h1:Hz2YULB3sN/aQA8cPSm2d6LM3E3qTMspzfRCIAD/1dc=
|
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 h1:j/ZeoAj185wHfCSYD52Kt/69i3Bzk1MXN4Qh1yP6+P4=
|
||||||
go.etztech.xyz/inspiro v0.0.0-20200606185551-edfdf9da2359/go.mod h1:+fC1WzJm/oS4UEgqr1jPouWerxBys52lTTDA94/5bf8=
|
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 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk=
|
||||||
go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g=
|
go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g=
|
||||||
go.jolheiser.com/gojang v0.0.2 h1:CvQETKT9sFfvuDeYVUkiR0Jh7xIs7Cayi0rZuDrXoZg=
|
go.jolheiser.com/gojang v0.0.3 h1:EWDLMo6X3f67DK2p/mSB680H43t8SDrDYNZnXvY7PLg=
|
||||||
go.jolheiser.com/gojang v0.0.2/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I=
|
go.jolheiser.com/gojang v0.0.3/go.mod h1:hUBULFDoampNM97E1IaYUhkLBJ30sb7iGsoFOdDU76I=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
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-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-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-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-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5 h1:iCaAy5bMeEvwANu3YnJfWwI0kWAGkEa2RXPdweI/ysk=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package imgur
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO Make a client for this in a separate module
|
||||||
|
|
||||||
|
var Images []*Image
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Images []*Image `json:"data"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Datetime int `json:"datetime"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Animated bool `json:"animated"`
|
||||||
|
Width int `json:"width"`
|
||||||
|
Height int `json:"height"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
Views int `json:"views"`
|
||||||
|
Bandwidth int `json:"bandwidth"`
|
||||||
|
Deletehash string `json:"deletehash"`
|
||||||
|
Section string `json:"section"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(clientID string) error {
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://api.imgur.com/3/album/TaJVIdQ/images", nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Client-ID %s", clientID))
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var imgurResp Response
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&imgurResp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
Images = imgurResp.Images
|
||||||
|
return resp.Body.Close()
|
||||||
|
}
|
2
main.go
2
main.go
|
@ -1,5 +1,3 @@
|
||||||
//go:generate go run sedbot.example.go
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue