Merge branch 'dev' of pocketjawa/discord-pocketbot-go into master
Version 1.0master v1.0
commit
47e23e8a0a
|
@ -0,0 +1,20 @@
|
||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
workspace:
|
||||||
|
base: /go
|
||||||
|
path: src/discord-pocketbot-go
|
||||||
|
steps:
|
||||||
|
- name: test
|
||||||
|
image: golang
|
||||||
|
commands:
|
||||||
|
- go get
|
||||||
|
- go build
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
repo: pocketjawa/discord-pocketbot
|
||||||
|
auto_tag: true
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
|
@ -0,0 +1,26 @@
|
||||||
|
# ---> Go
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
FROM golang:latest AS build
|
||||||
|
WORKDIR /go/src/discord-pocketbot
|
||||||
|
COPY . .
|
||||||
|
RUN go get -d -v ./...
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go install -v ./...
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
run apk add --no-cache ca-certificates
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /go/bin/discord-pocketbot discord-pocketbot
|
||||||
|
CMD ./discord-pocketbot
|
|
@ -0,0 +1,225 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/bwmarrin/disgord/x/mux"
|
||||||
|
"github.com/nishanths/go-xkcd"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Check member roles
|
||||||
|
func checkRole(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context, roleid string) bool {
|
||||||
|
if ctx.IsPrivate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
channel, _ := s.Channel(m.ChannelID)
|
||||||
|
guild := channel.GuildID
|
||||||
|
member, _ := s.GuildMember(guild, m.Author.ID)
|
||||||
|
for _, role := range member.Roles {
|
||||||
|
if role == roleid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generate a heckin swear word
|
||||||
|
func getSwear(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
resp := ""
|
||||||
|
swear, err := http.Get("https://swear.jawa.moe/")
|
||||||
|
if err != nil {
|
||||||
|
resp = "Error fetching swear: " + err.Error()
|
||||||
|
}
|
||||||
|
defer swear.Body.Close()
|
||||||
|
|
||||||
|
if swear.StatusCode == http.StatusOK {
|
||||||
|
body, err := ioutil.ReadAll(swear.Body)
|
||||||
|
if err != nil {
|
||||||
|
resp = "Error fetching swear: " + err.Error()
|
||||||
|
}
|
||||||
|
resp = string(body)
|
||||||
|
}
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Post the Maki Monday pic!
|
||||||
|
func makiMonday(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
resp := "https://maki.jawa.moe/monday.png"
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Post link to mixes B)
|
||||||
|
func postMixes(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
resp := "https://maki.jawa.moe/mixes/"
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Post a link to a random mix
|
||||||
|
func getRandomMix(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
|
||||||
|
//Define mix details
|
||||||
|
type Mix struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Mtime string `json:"mtime"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
mixresp, err := http.Get("https://maki.jawa.moe/mixesjson/")
|
||||||
|
if err != nil {
|
||||||
|
resp := "Error fetching mixes: " + err.Error()
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer mixresp.Body.Close()
|
||||||
|
|
||||||
|
if mixresp.StatusCode == http.StatusOK {
|
||||||
|
var mixes []*Mix
|
||||||
|
err = json.NewDecoder(mixresp.Body).Decode(&mixes)
|
||||||
|
rmix := mixes[rand.Intn(len(mixes))]
|
||||||
|
resp := "https://maki.jawa.moe/mixes/" + rmix.Name
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Post XKCD comic!
|
||||||
|
func getXKCD(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
resp := ""
|
||||||
|
xkclient := xkcd.NewClient()
|
||||||
|
var err error
|
||||||
|
var comic xkcd.Comic
|
||||||
|
var arg string
|
||||||
|
if len(ctx.Fields) > 1 {
|
||||||
|
arg = ctx.Fields[1]
|
||||||
|
} else {
|
||||||
|
arg = "random"
|
||||||
|
}
|
||||||
|
matchedNum, _ := regexp.MatchString(`^[0-9]+$`, arg)
|
||||||
|
if arg == "latest" {
|
||||||
|
comic, err = xkclient.Latest(context.Background())
|
||||||
|
} else if matchedNum {
|
||||||
|
comicNum, _ := strconv.Atoi(arg)
|
||||||
|
comic, err = xkclient.Get(context.Background(), comicNum)
|
||||||
|
} else {
|
||||||
|
latestcomic, _ := xkclient.Latest(context.Background())
|
||||||
|
randcomic := rand.Intn(latestcomic.Number)
|
||||||
|
comic, err = xkclient.Get(context.Background(), randcomic)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
resp = err.Error()
|
||||||
|
}
|
||||||
|
resp = comic.ImageURL
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Restart the bot
|
||||||
|
func restartBot(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
if !checkRole(s, m, ctx, bot_admin_role) {
|
||||||
|
resp := "OwO you aren't my daddy..."
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp := "Goodnight ;-;"
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
Session.Close()
|
||||||
|
log.Println("brb dying at the request of ", m.Author.String())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Morgana yells at you to sleep...
|
||||||
|
func goToSleep(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
embed := &discordgo.MessageEmbed{
|
||||||
|
Description: "Aren't you tired?\nLet's call it a day\nand get some sleep.",
|
||||||
|
Thumbnail: &discordgo.MessageEmbedThumbnail{
|
||||||
|
URL: "https://cdn.discordapp.com/emojis/396429379686629378.png",
|
||||||
|
},
|
||||||
|
Title: "Morgana",
|
||||||
|
}
|
||||||
|
s.ChannelMessageSendEmbed(m.ChannelID, embed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setNowPlaying(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
if !checkRole(s, m, ctx, bot_admin_role) {
|
||||||
|
resp := "OwO you aren't my daddy..."
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var resp string
|
||||||
|
if len(ctx.Fields) > 1 {
|
||||||
|
arg := strings.Join(ctx.Fields[1:], " ")
|
||||||
|
s.UpdateStatus(0, arg)
|
||||||
|
resp = "Now playing: " + arg
|
||||||
|
} else {
|
||||||
|
resp = "Please tell me what to play!"
|
||||||
|
}
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Roll any number of dice of the same kind
|
||||||
|
func diceRoller(dienum, diesides int) (total int, diceroles []string) {
|
||||||
|
for 0 < dienum {
|
||||||
|
dienum--
|
||||||
|
rollresult := rand.Intn(diesides) + 1
|
||||||
|
total += rollresult
|
||||||
|
diceroles = append(diceroles, "D"+strconv.Itoa(diesides)+": **"+strconv.Itoa(rollresult)+"**")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Dice rolling command
|
||||||
|
func rollDice(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
var resp string
|
||||||
|
var diceroles []string
|
||||||
|
var dicetotal int
|
||||||
|
var matchDicePattern = regexp.MustCompile(`^[0-9]*[Dd][1-9][0-9]*$`)
|
||||||
|
var args = ctx.Fields[1:]
|
||||||
|
for i := range args {
|
||||||
|
if matchDicePattern.MatchString(args[i]) {
|
||||||
|
dLocation := strings.Index(strings.ToLower(args[i]), "d")
|
||||||
|
dienum, _ := strconv.Atoi(args[i][:dLocation])
|
||||||
|
diesides, _ := strconv.Atoi(args[i][dLocation+1:])
|
||||||
|
if dienum == 0 {
|
||||||
|
dienum = 1
|
||||||
|
}
|
||||||
|
resultsTotal, resultsRolls := diceRoller(dienum, diesides)
|
||||||
|
if dienum > 25 {
|
||||||
|
diceroles = append(diceroles, strconv.Itoa(dienum)+"*D"+strconv.Itoa(diesides)+": **"+strconv.Itoa(resultsTotal)+"**")
|
||||||
|
} else {
|
||||||
|
diceroles = append(diceroles, resultsRolls...)
|
||||||
|
}
|
||||||
|
dicetotal += resultsTotal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results := strings.Join(diceroles, ", ")
|
||||||
|
resp = m.Author.Username + " rolled " + results + ", for a total of **" + strconv.Itoa(dicetotal) + "**!"
|
||||||
|
if dicetotal == 0 {
|
||||||
|
resp = "Oops, looks like no dice were rolled! Try something like `!roll d20`, `!roll 2d6`, or `!roll 3d6 d20` instead."
|
||||||
|
}
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ask the Magic Conch shell to predict the future!
|
||||||
|
func askConch(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
var resp string
|
||||||
|
if len(ctx.Fields) > 1 {
|
||||||
|
conchResponses := []string{"It is certain", "It is decidedly so", "Without a doubt", "Yes definitely", "You may rely on it", "As I see it, yes", "Most likely", "Outlook good", "Yes", "Signs point to yes", "Reply hazy try again", "Ask again later", "Better not tell you now", "Cannot predict now", "Concentrate and ask again", "Don't count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"}
|
||||||
|
resp = conchResponses[rand.Intn(len(conchResponses))]
|
||||||
|
} else {
|
||||||
|
resp = "The Magic Conch™ may be able to see into the future, but it can't read your mind! Please include a question."
|
||||||
|
}
|
||||||
|
s.ChannelMessageSend(m.ChannelID, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test command that says UwU
|
||||||
|
func sayUwU(s *discordgo.Session, m *discordgo.Message, ctx *mux.Context) {
|
||||||
|
s.ChannelMessageSend(m.ChannelID, "UwU *nuzzles*")
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/bwmarrin/disgord/x/mux"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Session, _ = discordgo.New()
|
||||||
|
var bot_token string
|
||||||
|
var bot_channel string
|
||||||
|
var bot_admin_role string
|
||||||
|
var Router = mux.New()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
flag.StringVar(&bot_token, "t", "", "Discord Authentication Token")
|
||||||
|
flag.StringVar(&bot_channel, "bc", "", "Bot status channel")
|
||||||
|
flag.Parse()
|
||||||
|
if os.Getenv("DISCORD_TOKEN") != "" {
|
||||||
|
Session.Token = "Bot " + os.Getenv("DISCORD_TOKEN")
|
||||||
|
} else {
|
||||||
|
Session.Token = "Bot " + bot_token
|
||||||
|
}
|
||||||
|
if os.Getenv("DISCORD_BOT_CHANNEL") != "" {
|
||||||
|
bot_channel = os.Getenv("DISCORD_BOT_CHANNEL")
|
||||||
|
}
|
||||||
|
if os.Getenv("POCKETBOT_ADMIN_ROLE") != "" {
|
||||||
|
bot_admin_role = os.Getenv("POCKETBOT_ADMIN_ROLE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
fmt.Println("pocketbot")
|
||||||
|
//flag.Parse()
|
||||||
|
if Session.Token == "" {
|
||||||
|
log.Println("You must provide a Discord auth token!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handlers
|
||||||
|
Session.AddHandler(ready)
|
||||||
|
Session.AddHandler(Router.OnMessageCreate)
|
||||||
|
|
||||||
|
//Set the command prefix
|
||||||
|
if os.Getenv("POCKETBOT_PREFIX") != "" {
|
||||||
|
Router.Prefix = os.Getenv("POCKETBOT_PREFIX")
|
||||||
|
} else {
|
||||||
|
Router.Prefix = "!"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the build-in help command.
|
||||||
|
Router.Route("help", "Display this message.", Router.Help)
|
||||||
|
Router.Route("swear", "Make me swear!", getSwear)
|
||||||
|
Router.Route("maki", "It's Maki Monday my dudes!", makiMonday)
|
||||||
|
Router.Route("monday", "It's Maki Monday my dudes!", makiMonday)
|
||||||
|
Router.Route("mixes", "Post the link to my fire mixtapes!", postMixes)
|
||||||
|
Router.Route("rmix", "Post a random mix!", getRandomMix)
|
||||||
|
Router.Route("xkcd", "Post a specific, random, or the latest XKCD comic", getXKCD)
|
||||||
|
Router.Route("restart", "Restart the bot.", restartBot)
|
||||||
|
Router.Route("kill", "Restart the bot.", restartBot)
|
||||||
|
Router.Route("sleep", "Something about sleeping...", goToSleep)
|
||||||
|
Router.Route("setplaying", "Set the nowplaying message for the bot.", setNowPlaying)
|
||||||
|
Router.Route("roll", "Roll some dice!", rollDice)
|
||||||
|
Router.Route("conch", "Ask the Magic Conch™ shell to predict the future!", askConch)
|
||||||
|
Router.Route("uwu", "Say UwU", sayUwU)
|
||||||
|
|
||||||
|
//Open a connection to Discord
|
||||||
|
err = Session.Open()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error opening connection to Discord, %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Wait for a CTRL-C
|
||||||
|
log.Printf("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
|
||||||
|
Session.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ready(s *discordgo.Session, event *discordgo.Ready) {
|
||||||
|
s.UpdateStatus(0, "with droids!")
|
||||||
|
if os.Getenv("POCKETBOT_STARTUP_MESSAGE") == "TRUE" {
|
||||||
|
s.ChannelMessageSend(bot_channel, "This isn't Tatooine...")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
Loading…
Reference in New Issue