mirror of https://github.com/hak5/scuzzy.git
Create Scuzzy
Features: Hastily add usercolor feature Main: Show prefix in bot status Features: add cat Main/Features/Auth: Add basic Role Name/ID based command authentication and bot configuration. Main: Sanity check for missing flags. Features: Implement command deletion and tag-responses Misc: Add cmd/main to .gitignore Misc: Delete built binary Main: Refactor main.go - Use log.Fatal instead of fmt.Printf and os.Exit - Move Config reading into seperate function - Parse command line flags in main() - Instantiate Features.go struct inside main() - Use simple ticker to set bot status every 15 minutes Auth: Refactor auth - Return early when building Admin role list - Move CheckAdminrole() into auth.go, remove roles.go Features: Refactor features - Remove New() function - Move help.go, ping.go functionality into misc.go Features: Add bot control feature to set status. Features: Implement helper function for embeds, return errors. Main: Rename config file to bot_config.json Features: Use success embed for user color. Features: Add purge messages feature. Main: Add status_text property to config, use it for Bot Status. Features: Send welcome message to new users, implement auto-join roles. Main: Use complex user status Main: Reduce ticker interval to 10 minutes for bot status update. Main: Create helper function for complex custom embeds. Features: Implement info command. Features: Convert requested user color to lowercase. Features: Add markdown helper Features: Fix markdown helper typo Features: Use error embed for handleSetStatus incorrect permissions. Features: Add strikethrough and spoilers information to markdown info. Features: Add info and md to help text. Features: Use backtick instead of single quote for command prefix in help text. Features: Remove markdown info message after 15 seconds. Features: Fix typo in status setting permission error. Features: Add commands to convert between Celsius and Farenheit Features: Update help to include temperature conversion commands. Features/Models/Main: Load color roles from JSON config. Auth/Main/Features/Models: Implement config-based channel white/blacklisting. Main/Models: Remove unused admin_only config field. Features: Simplify error handling. Auth: Remove leftover AdminOnly field. Features: Use command restriction for usercolor commands. Main: Update default config to restrict color and colors commands. Auth/Features: Return true for undefined commands in restrictions list by default. Features: Use better error messages for channel white/blacklist Auth: Improve channel white/blacklist behavior. Main: Replace broken ticker for status updates Features: Get bot avatar via Discord for embed. Features: Delete requesting message for markdown info. Features: Handle potential error in deleting help requester message.master
commit
d54d2bb812
|
@ -0,0 +1,3 @@
|
|||
.idea/
|
||||
main
|
||||
cmd/main
|
|
@ -0,0 +1,92 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"github.com/bwmarrin/discord.go"
|
||||
"github.com/foxtrot/scuzzy/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AdminRole struct {
|
||||
Name string
|
||||
ID string
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
AdminRoles []AdminRole
|
||||
CommandRestrictions []models.CommandRestriction
|
||||
Guild *discordgo.Guild
|
||||
|
||||
Config *models.Configuration
|
||||
}
|
||||
|
||||
func New(config *models.Configuration, guild *discordgo.Guild) *Auth {
|
||||
var ars []AdminRole
|
||||
for _, gRole := range guild.Roles {
|
||||
for _, aRole := range config.AdminRoles {
|
||||
if aRole != gRole.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
ar := AdminRole{
|
||||
Name: gRole.Name,
|
||||
ID: gRole.ID,
|
||||
}
|
||||
ars = append(ars, ar)
|
||||
}
|
||||
}
|
||||
|
||||
var crs []models.CommandRestriction
|
||||
for _, cRes := range config.CommandRestrictions {
|
||||
cr := models.CommandRestriction{
|
||||
Command: cRes.Command,
|
||||
Mode: cRes.Mode,
|
||||
Channels: cRes.Channels,
|
||||
}
|
||||
crs = append(crs, cr)
|
||||
}
|
||||
|
||||
return &Auth{
|
||||
AdminRoles: ars,
|
||||
CommandRestrictions: crs,
|
||||
Config: config,
|
||||
Guild: guild,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Auth) CheckAdminRole(m *discordgo.Member) bool {
|
||||
for _, aR := range a.AdminRoles {
|
||||
for _, mID := range m.Roles {
|
||||
if aR.ID == mID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *Auth) CheckCommandRestrictions(m *discordgo.MessageCreate) bool {
|
||||
cName := strings.Split(m.Content, " ")[0]
|
||||
cName = strings.Replace(cName, a.Config.CommandKey, "", 1)
|
||||
cChanID := m.ChannelID
|
||||
|
||||
for _, cR := range a.CommandRestrictions {
|
||||
if cName == cR.Command {
|
||||
for _, cID := range cR.Channels {
|
||||
if cID == cChanID && cR.Mode == "white" {
|
||||
return true
|
||||
} else if cID == cChanID && cR.Mode == "black" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if cR.Mode == "white" {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"guild_id": "506629366659153951",
|
||||
|
||||
"status_text": ".help",
|
||||
"welcome_text": "Hi! Welcome to the Hak5 Discord Server. Please be sure to check out the #rules channel and say hello in #general!",
|
||||
"command_key": ".",
|
||||
|
||||
"admin_roles": ["Admin", "Moderator"],
|
||||
"join_role_ids": ["697929841638637778"],
|
||||
|
||||
"command_restrictions": [
|
||||
{ "command": "color", "mode": "white", "channels": ["698567678025138277", "698519835532984470"] },
|
||||
{ "command": "colors", "mode": "white", "channels": ["698567678025138277", "698519835532984470"] }
|
||||
],
|
||||
|
||||
"color_roles": [
|
||||
{ "color": "red", "id": "697930042491142174" },
|
||||
{ "color": "blue", "id": "697930093766639699" },
|
||||
{ "color": "green", "id": "697930441939877970" },
|
||||
{ "color": "purple", "id": "697930578485444610" },
|
||||
{ "color": "yellow", "id": "697930630247350402" },
|
||||
{ "color": "pink", "id": "697965484313935966" }
|
||||
]
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/foxtrot/scuzzy/auth"
|
||||
"github.com/foxtrot/scuzzy/features"
|
||||
"github.com/foxtrot/scuzzy/models"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/bwmarrin/discord.go"
|
||||
)
|
||||
|
||||
// Core Bot Properties
|
||||
var (
|
||||
Token string
|
||||
ConfigPath string
|
||||
Config models.Configuration
|
||||
)
|
||||
|
||||
func getConfig() error {
|
||||
cf, err := ioutil.ReadFile(ConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(cf, &Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Parse and Check Flags
|
||||
flag.StringVar(&Token, "t", "", "Bot Token")
|
||||
flag.StringVar(&ConfigPath, "c", "", "Config Path")
|
||||
flag.Parse()
|
||||
|
||||
if len(Token) == 0 {
|
||||
log.Fatal("Error: No Auth Token supplied.")
|
||||
}
|
||||
if len(ConfigPath) == 0 {
|
||||
log.Fatal("Error: No Config Path supplied.")
|
||||
}
|
||||
|
||||
// Get Config
|
||||
err := getConfig()
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
// Instantiate Bot
|
||||
bot, err := discordgo.New("Bot " + Token)
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
// Open Connection
|
||||
err = bot.Open()
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
// Setup Auth
|
||||
Config.Guild, err = bot.Guild(Config.GuildID)
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
var a *auth.Auth
|
||||
a = auth.New(&Config, Config.Guild)
|
||||
|
||||
// Setup Handlers
|
||||
f := features.Features{
|
||||
Token: Token,
|
||||
Auth: a,
|
||||
Config: Config,
|
||||
}
|
||||
|
||||
// Register Handlers
|
||||
bot.AddHandler(f.OnMessageCreate)
|
||||
bot.AddHandler(f.OnUserJoin)
|
||||
|
||||
fmt.Println("Bot Running.")
|
||||
|
||||
// Set Bot Status
|
||||
go func() {
|
||||
usd := discordgo.UpdateStatusData{
|
||||
IdleSince: nil,
|
||||
Game: &discordgo.Game{
|
||||
Name: Config.StatusText,
|
||||
Type: 0,
|
||||
URL: "",
|
||||
Details: "",
|
||||
State: "",
|
||||
TimeStamps: discordgo.TimeStamps{},
|
||||
Assets: discordgo.Assets{},
|
||||
ApplicationID: "",
|
||||
Instance: -1,
|
||||
},
|
||||
AFK: false,
|
||||
Status: "online",
|
||||
}
|
||||
err = bot.UpdateStatusComplex(usd)
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
|
||||
// For some reason the bot's status will regularly disappear...
|
||||
for _ = range time.Tick(10 * time.Minute) {
|
||||
err := bot.UpdateStatusComplex(usd)
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Catch SIGINT
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGKILL)
|
||||
<-sc
|
||||
|
||||
err = bot.Close()
|
||||
if err != nil {
|
||||
log.Fatal("Error: " + err.Error())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"errors"
|
||||
discordgo "github.com/bwmarrin/discord.go"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *Features) handleSetStatus(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
if !f.Auth.CheckAdminRole(m.Member) {
|
||||
return errors.New("You do not have permissions to use that command.")
|
||||
}
|
||||
|
||||
stSplit := strings.SplitN(m.Content, " ", 2)
|
||||
if len(stSplit) < 2 {
|
||||
return errors.New("You did not specify a status.")
|
||||
}
|
||||
|
||||
st := stSplit[1]
|
||||
|
||||
err := s.UpdateStatus(0, st)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := f.CreateDefinedEmbed("Set Status", "Operation completed successfully.", "success")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"github.com/foxtrot/scuzzy/auth"
|
||||
"github.com/foxtrot/scuzzy/models"
|
||||
)
|
||||
|
||||
type Features struct {
|
||||
Token string
|
||||
Auth *auth.Auth
|
||||
Config models.Configuration
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"github.com/bwmarrin/discord.go"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *Features) OnMessageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
var err error
|
||||
|
||||
// Ignore the bot itself
|
||||
if m.Author.ID == s.State.User.ID {
|
||||
return
|
||||
}
|
||||
|
||||
cKey := f.Config.CommandKey
|
||||
cName := strings.Split(m.Content, " ")[0]
|
||||
|
||||
if !strings.HasPrefix(cName, cKey) {
|
||||
return
|
||||
}
|
||||
|
||||
switch cName {
|
||||
/* Misc Commands */
|
||||
case cKey + "help":
|
||||
err = f.handleHelp(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Help)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "info":
|
||||
err = f.handleInfo(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Info)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "ping":
|
||||
err = f.handlePing(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Ping)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "no":
|
||||
err = f.handleCat(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (No)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "md":
|
||||
err = f.handleMarkdownInfo(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Markdown)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "ctof":
|
||||
err = f.handleCtoF(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (CtoF)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "ftoc":
|
||||
err = f.handleFtoC(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (FtoC)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
/* Moderation */
|
||||
case cKey + "purge":
|
||||
err = f.handlePurgeChannel(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Purge)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
/* Bot Control */
|
||||
case cKey + "status":
|
||||
err = f.handleSetStatus(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Status)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
/* Role Colors */
|
||||
case cKey + "colors":
|
||||
err = f.listUserColors(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Colors)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
case cKey + "color":
|
||||
err = f.setUserColor(s, m)
|
||||
if err != nil {
|
||||
eMsg := f.CreateDefinedEmbed("Error (Color)", err.Error(), "error")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, eMsg)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Features) OnUserJoin(s *discordgo.Session, m *discordgo.GuildMemberAdd) {
|
||||
userChannel, err := s.UserChannelCreate(m.User.ID)
|
||||
if err != nil {
|
||||
log.Print("Error (User Join): " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.ChannelMessageSend(userChannel.ID, f.Config.WelcomeText)
|
||||
if err != nil {
|
||||
log.Print("Error (User Join): " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for _, roleID := range f.Config.JoinRoleIDs {
|
||||
err = s.GuildMemberRoleAdd(f.Auth.Guild.ID, m.User.ID, roleID)
|
||||
if err != nil {
|
||||
log.Print("Error (User Join)" + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
discordgo "github.com/bwmarrin/discord.go"
|
||||
"github.com/foxtrot/scuzzy/models"
|
||||
)
|
||||
|
||||
func (f *Features) PrintError(component string, error string) {
|
||||
fmt.Printf("Error: %s: %s\n", component, error)
|
||||
}
|
||||
|
||||
func (f *Features) CreateDefinedEmbed(title string, desc string, status string) *discordgo.MessageEmbed {
|
||||
msgColor := 0x000000
|
||||
|
||||
switch status {
|
||||
case "error":
|
||||
msgColor = 0xCC0000
|
||||
break
|
||||
case "success":
|
||||
msgColor = 0x00CC00
|
||||
break
|
||||
default:
|
||||
msgColor = 0xFFA500
|
||||
}
|
||||
|
||||
ftr := discordgo.MessageEmbedFooter{
|
||||
Text: "Something broken? Tell foxtrot#1337",
|
||||
IconURL: "https://cdn.discordapp.com/avatars/514163441548656641/a4ede220fea0ad8872b86f3eebc45524.png?size=128",
|
||||
ProxyIconURL: "",
|
||||
}
|
||||
|
||||
msg := discordgo.MessageEmbed{
|
||||
URL: "",
|
||||
Type: "",
|
||||
Title: title,
|
||||
Description: desc,
|
||||
Timestamp: "",
|
||||
Color: msgColor,
|
||||
Footer: &ftr,
|
||||
Image: nil,
|
||||
Thumbnail: nil,
|
||||
Video: nil,
|
||||
Provider: nil,
|
||||
Author: nil,
|
||||
Fields: nil,
|
||||
}
|
||||
|
||||
return &msg
|
||||
}
|
||||
|
||||
func (f *Features) CreateCustomEmbed(embedData *models.CustomEmbed) *discordgo.MessageEmbed {
|
||||
var ftr discordgo.MessageEmbedFooter
|
||||
var img discordgo.MessageEmbedImage
|
||||
var thm discordgo.MessageEmbedThumbnail
|
||||
var prv discordgo.MessageEmbedProvider
|
||||
var atr discordgo.MessageEmbedAuthor
|
||||
|
||||
ftr.Text = embedData.FooterText
|
||||
ftr.IconURL = embedData.FooterImageURL
|
||||
|
||||
img.URL = embedData.ImageURL
|
||||
img.Height = embedData.ImageH
|
||||
img.Width = embedData.ImageW
|
||||
|
||||
thm.URL = embedData.ThumbnailURL
|
||||
thm.Height = embedData.ThumbnailH
|
||||
thm.Width = embedData.ThumbnailW
|
||||
|
||||
prv.Name = embedData.ProviderText
|
||||
prv.URL = embedData.ProviderURL
|
||||
|
||||
atr.Name = embedData.AuthorText
|
||||
atr.URL = embedData.AuthorURL
|
||||
atr.IconURL = embedData.AuthorImageURL
|
||||
|
||||
msg := discordgo.MessageEmbed{
|
||||
URL: embedData.URL,
|
||||
Type: embedData.Type,
|
||||
Title: embedData.Title,
|
||||
Description: embedData.Desc,
|
||||
Timestamp: "",
|
||||
Color: embedData.Color,
|
||||
Footer: &ftr,
|
||||
Image: &img,
|
||||
Thumbnail: &thm,
|
||||
Video: nil,
|
||||
Provider: &prv,
|
||||
Author: &atr,
|
||||
Fields: nil,
|
||||
}
|
||||
|
||||
return &msg
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bwmarrin/discord.go"
|
||||
"github.com/foxtrot/scuzzy/models"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (f *Features) handleCat(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
if f.Auth.CheckAdminRole(m.Member) {
|
||||
_, _ = s.ChannelMessageSend(m.ChannelID, "https://giphy.com/gifs/cat-cute-no-rCxogJBzaeZuU")
|
||||
_ = s.ChannelMessageDelete(m.ChannelID, m.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handlePing(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
var r *discordgo.Message
|
||||
var err error
|
||||
|
||||
if !f.Auth.CheckAdminRole(m.Member) {
|
||||
return errors.New("You do not have permissions to use that command.")
|
||||
} else {
|
||||
msg := f.CreateDefinedEmbed("Ping", "Pong", "success")
|
||||
r, err = s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
err = s.ChannelMessageDelete(m.ChannelID, r.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.ChannelMessageDelete(m.ChannelID, m.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handleInfo(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
desc := "**Source**: https://github.com/foxtrot/scuzzy\n"
|
||||
desc += "**Language**: Go\n"
|
||||
desc += "**Commands**: See `" + f.Config.CommandKey + "help`\n\n\n"
|
||||
|
||||
gm, err := s.GuildMember(f.Config.GuildID, s.State.User.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d := models.CustomEmbed{
|
||||
Title: "Scuzzy Information",
|
||||
Desc: desc,
|
||||
ImageURL: "",
|
||||
ImageH: 100,
|
||||
ImageW: 100,
|
||||
Color: 0xFFA500,
|
||||
URL: "",
|
||||
Type: "",
|
||||
Timestamp: "",
|
||||
FooterText: "Made with ❤ by Foxtrot",
|
||||
FooterImageURL: "https://cdn.discordapp.com/avatars/514163441548656641/a4ede220fea0ad8872b86f3eebc45524.png",
|
||||
ThumbnailURL: gm.User.AvatarURL(""),
|
||||
ThumbnailH: 150,
|
||||
ThumbnailW: 150,
|
||||
ProviderURL: "",
|
||||
ProviderText: "",
|
||||
AuthorText: "",
|
||||
AuthorURL: "",
|
||||
AuthorImageURL: "",
|
||||
}
|
||||
|
||||
msg := f.CreateCustomEmbed(&d)
|
||||
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handleHelp(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
desc := "**Available Commands**\n"
|
||||
desc += "`help` - This help dialog\n"
|
||||
desc += "`info` - Display Scuzzy info\n"
|
||||
desc += "`md` - Display Discord markdown information\n"
|
||||
desc += "`colors` - Available color roles\n"
|
||||
desc += "`color` - Set an available color role\n"
|
||||
desc += "`ctof` - Convert Celsius to Farenheit\n"
|
||||
desc += "`ftoc` - Convert Farenheit to Celsius\n"
|
||||
|
||||
if f.Auth.CheckAdminRole(m.Member) {
|
||||
desc += "\n"
|
||||
desc += "**Admin Commands**\n"
|
||||
desc += "`ping` - Ping the bot\n"
|
||||
desc += "`status` - Set the bot status\n"
|
||||
desc += "`purge` - Purge channel messages\n"
|
||||
}
|
||||
|
||||
desc += "\n\nAll commands are prefixed with `" + f.Config.CommandKey + "`\n"
|
||||
|
||||
msg := f.CreateDefinedEmbed("Help", desc, "")
|
||||
|
||||
_, err := s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.ChannelMessageDelete(m.ChannelID, m.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handleMarkdownInfo(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
desc := "*Italic* text goes between `*single asterisks*`\n"
|
||||
desc += "**Bold** text goes between `**double asterisks**`\n"
|
||||
desc += "***Bold and Italic*** text goes between `***triple asterisks***`\n"
|
||||
desc += "__Underlined__ text goes between `__double underscore__`\n"
|
||||
desc += "~~Strikethrough~~ text goes between `~~double tilde~~`\n"
|
||||
desc += "||Spoilers|| go between `|| double pipe ||`\n\n"
|
||||
desc += "You can combine the above styles.\n\n"
|
||||
desc += "Inline Code Blocks start and end with a single `````\n"
|
||||
desc += "Multi line Code Blocks start and end with ```````\n"
|
||||
desc += "Multi line Code Blocks can also specify a language with `````language`` at the start\n\n"
|
||||
desc += "Single line quotes start with `>`\n"
|
||||
desc += "Multi line quotes start with `>>>`\n"
|
||||
|
||||
msg := f.CreateDefinedEmbed("Discord Markdown", desc, "")
|
||||
r, err := s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(15 * time.Second)
|
||||
|
||||
err = s.ChannelMessageDelete(m.ChannelID, r.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.ChannelMessageDelete(m.ChannelID, m.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handleCtoF(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
inS := strings.Split(m.Content, " ")
|
||||
|
||||
if len(inS) < 2 {
|
||||
return errors.New("You did not specify a temperature")
|
||||
}
|
||||
in := inS[1]
|
||||
|
||||
inF, err := strconv.ParseFloat(in, 2)
|
||||
if err != nil {
|
||||
return errors.New("You did not specify a valid number")
|
||||
}
|
||||
|
||||
cels := (inF * 9.0 / 5.0) + 32.0
|
||||
celsF := float64(cels)
|
||||
|
||||
msg := fmt.Sprintf("`%.1f°c` is `%.1f°f`", inF, celsF)
|
||||
|
||||
e := f.CreateDefinedEmbed("Celsius to Farenheit", msg, "")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) handleFtoC(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
inS := strings.Split(m.Content, " ")
|
||||
|
||||
if len(inS) < 2 {
|
||||
return errors.New("You did not specify a temperature")
|
||||
}
|
||||
in := inS[1]
|
||||
|
||||
inF, err := strconv.ParseFloat(in, 2)
|
||||
if err != nil {
|
||||
return errors.New("You did not specify a valid number")
|
||||
}
|
||||
|
||||
faren := (inF - 32) * 5 / 9
|
||||
farenF := float64(faren)
|
||||
|
||||
msg := fmt.Sprintf("`%.1f°f` is `%.1f°c`", inF, farenF)
|
||||
|
||||
e := f.CreateDefinedEmbed("Farenheit to Celsius", msg, "")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/bwmarrin/discord.go"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *Features) handlePurgeChannel(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
if !f.Auth.CheckAdminRole(m.Member) {
|
||||
return errors.New("You do not have permissions to use that command.")
|
||||
}
|
||||
|
||||
purgeSplit := strings.SplitN(m.Content, " ", 2)
|
||||
if len(purgeSplit) < 2 {
|
||||
return errors.New("No message count supplied")
|
||||
}
|
||||
|
||||
msgCount, err := strconv.Atoi(purgeSplit[1])
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if msgCount > 100 {
|
||||
return errors.New("You may only purge upto 100 messages at a time.")
|
||||
}
|
||||
|
||||
chanMsgs, err := s.ChannelMessages(m.ChannelID, msgCount, "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := f.CreateDefinedEmbed("Purge Channel", "Purging `"+purgeSplit[1]+"` messages.", "normal")
|
||||
r, err := s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var delMsgs []string
|
||||
for _, v := range chanMsgs {
|
||||
delMsgs = append(delMsgs, v.ID)
|
||||
}
|
||||
|
||||
err = s.ChannelMessagesBulkDelete(m.ChannelID, delMsgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.ChannelMessageDelete(m.ChannelID, r.ID)
|
||||
msg = f.CreateDefinedEmbed("Purge Channel", "Purged `"+purgeSplit[1]+"` messages!", "success")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package features
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/bwmarrin/discord.go"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *Features) listUserColors(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
if !f.Auth.CheckCommandRestrictions(m) {
|
||||
return errors.New("This command is not allowed in this channel.")
|
||||
}
|
||||
|
||||
msgC := "You can choose from the following colors:\n\n"
|
||||
for _, v := range f.Config.ColorRoles {
|
||||
msgC += "<@&" + v.ID + ">\n"
|
||||
}
|
||||
msgC += "\n\nUse `" + f.Config.CommandKey + "color <color_name>` to set.\n"
|
||||
|
||||
msg := f.CreateDefinedEmbed("User Colors", msgC, "")
|
||||
|
||||
_, err := s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Features) setUserColor(s *discordgo.Session, m *discordgo.MessageCreate) error {
|
||||
var err error
|
||||
|
||||
if !f.Auth.CheckCommandRestrictions(m) {
|
||||
return errors.New("This command is not allowed in this channel.")
|
||||
}
|
||||
|
||||
rUserID := m.Author.ID
|
||||
|
||||
userInput := strings.Split(m.Content, " ")
|
||||
if len(userInput) < 2 {
|
||||
err = f.listUserColors(s, m)
|
||||
return err
|
||||
}
|
||||
roleColorName := userInput[1]
|
||||
roleColorName = strings.ToLower(roleColorName)
|
||||
|
||||
roleColorID := ""
|
||||
for _, role := range f.Config.ColorRoles {
|
||||
if role.Name == roleColorName {
|
||||
roleColorID = role.ID
|
||||
}
|
||||
}
|
||||
if len(roleColorID) == 0 {
|
||||
err = f.listUserColors(s, m)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, role := range f.Config.ColorRoles {
|
||||
// Attempt to remove all color roles regardless of if they have them or not.
|
||||
// Slow because of the REST requests...
|
||||
_ = s.GuildMemberRoleRemove(m.GuildID, rUserID, role.ID)
|
||||
}
|
||||
|
||||
err = s.GuildMemberRoleAdd(m.GuildID, rUserID, roleColorID)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
msg := f.CreateDefinedEmbed("User Color", "<@"+m.Author.ID+">: Your color has been set to <@&"+roleColorID+">!", "success")
|
||||
_, err = s.ChannelMessageSendEmbed(m.ChannelID, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = s.ChannelMessageDelete(m.ChannelID, m.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package models
|
||||
|
||||
import "github.com/bwmarrin/discord.go"
|
||||
|
||||
type ColorRole struct {
|
||||
Name string `json:"color"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type CommandRestriction struct {
|
||||
Command string `json:"command"`
|
||||
Mode string `json:"mode"`
|
||||
Channels []string `json:"channels"`
|
||||
}
|
||||
|
||||
type Configuration struct {
|
||||
GuildID string `json:"guild_id"`
|
||||
|
||||
StatusText string `json:"status_text"`
|
||||
WelcomeText string `json:"welcome_text"`
|
||||
CommandKey string `json:"command_key"`
|
||||
|
||||
AdminRoles []string `json:"admin_roles"`
|
||||
JoinRoleIDs []string `json:"join_role_ids"`
|
||||
|
||||
CommandRestrictions []CommandRestriction `json:"command_restrictions"`
|
||||
|
||||
ColorRoles []ColorRole `json:"color_roles"`
|
||||
|
||||
Guild *discordgo.Guild `json:"reserved_guild"`
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package models
|
||||
|
||||
type CustomEmbed struct {
|
||||
URL string
|
||||
Title string
|
||||
Desc string
|
||||
Type string
|
||||
Timestamp string
|
||||
Color int
|
||||
|
||||
FooterText string
|
||||
FooterImageURL string
|
||||
|
||||
ImageURL string
|
||||
ImageH int
|
||||
ImageW int
|
||||
|
||||
ThumbnailURL string
|
||||
ThumbnailH int
|
||||
ThumbnailW int
|
||||
|
||||
ProviderURL string
|
||||
ProviderText string
|
||||
|
||||
AuthorText string
|
||||
AuthorURL string
|
||||
AuthorImageURL string
|
||||
}
|
Loading…
Reference in New Issue