Repo Reorg

This commit is contained in:
Dustin Pianalto
2020-09-18 18:39:51 -08:00
parent af506f828d
commit d9e1efbaf0
33 changed files with 489 additions and 352 deletions
+64
View File
@@ -0,0 +1,64 @@
package discord_utils
import (
"fmt"
"time"
)
func ParseDateString(inTime time.Time) string {
d := time.Now().Sub(inTime)
s := int64(d.Seconds())
days := s / 86400
s = s - (days * 86400)
hours := s / 3600
s = s - (hours * 3600)
minutes := s / 60
seconds := s - (minutes * 60)
dateString := ""
if days != 0 {
dateString += fmt.Sprintf("%v days ", days)
}
if hours != 0 {
dateString += fmt.Sprintf("%v hours ", hours)
}
if minutes != 0 {
dateString += fmt.Sprintf("%v minutes ", minutes)
}
if seconds != 0 {
dateString += fmt.Sprintf("%v seconds ", seconds)
}
if dateString != "" {
dateString += " ago."
} else {
dateString = "Now"
}
stamp := inTime.Format("2006-01-02 15:04:05")
return fmt.Sprintf("%v\n%v", dateString, stamp)
}
func ParseDurationString(inDur time.Duration) string {
s := int64(inDur.Seconds())
days := s / 86400
s = s - (days * 86400)
hours := s / 3600
s = s - (hours * 3600)
minutes := s / 60
seconds := s - (minutes * 60)
durString := ""
if days != 0 {
durString += fmt.Sprintf("%v days ", days)
}
if hours != 0 {
durString += fmt.Sprintf("%v hours ", hours)
}
if minutes != 0 {
durString += fmt.Sprintf("%v minutes ", minutes)
}
if seconds != 0 {
durString += fmt.Sprintf("%v seconds ", seconds)
}
if durString == "" {
durString = "0 seconds"
}
return fmt.Sprintf("%v", durString)
}
+32
View File
@@ -0,0 +1,32 @@
package discord_utils
import "time"
type Snowflake struct {
CreationTime time.Time
WorkerID int8
ProcessID int8
Increment int16
}
func ParseSnowflake(s int64) Snowflake {
const (
DISCORD_EPOCH = 1420070400000
TIME_BITS_LOC = 22
WORKER_ID_LOC = 17
WORKER_ID_MASK = 0x3E0000
PROCESS_ID_LOC = 12
PROCESS_ID_MASK = 0x1F000
INCREMENT_MASK = 0xFFF
)
creationTime := time.Unix(((s>>TIME_BITS_LOC)+DISCORD_EPOCH)/1000.0, 0)
workerID := (s & WORKER_ID_MASK) >> WORKER_ID_LOC
processID := (s & PROCESS_ID_MASK) >> PROCESS_ID_LOC
increment := s & INCREMENT_MASK
return Snowflake{
CreationTime: creationTime,
WorkerID: int8(workerID),
ProcessID: int8(processID),
Increment: int16(increment),
}
}
+36
View File
@@ -0,0 +1,36 @@
package events
import (
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/postgres"
)
var LoggingChannel = make(chan *LogEvent, 10)
type LogEvent struct {
// Embed with log message
Embed discordgo.MessageEmbed
// Guild to log event in
GuildID string
// Discordgo Session. Needed for sending messages
Session *discordgo.Session
}
func LoggingHandler(lc chan *LogEvent) {
for event := range lc {
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", event.GuildID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
return
}
if channelID == "" {
return
}
_, _ = event.Session.ChannelMessageSendEmbed(channelID, &event.Embed)
}
}
+167
View File
@@ -0,0 +1,167 @@
package events
import (
"fmt"
"log"
"strconv"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/discord_utils"
"github.com/dustinpianalto/goff/internal/postgres"
)
func OnGuildMemberAddLogging(s *discordgo.Session, member *discordgo.GuildMemberAdd) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnGuildMemberAddLogging", r)
}
}()
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
}
guild, err := s.State.Guild(member.GuildID)
if err != nil {
log.Println(err)
return
}
var title string
if member.User.Bot {
title = "Bot Joined"
} else {
title = "Member Joined"
}
thumb := &discordgo.MessageEmbedThumbnail{
URL: member.User.AvatarURL(""),
}
int64ID, _ := strconv.ParseInt(member.User.ID, 10, 64)
snow := discord_utils.ParseSnowflake(int64ID)
field := &discordgo.MessageEmbedField{
Name: "User was created:",
Value: discord_utils.ParseDateString(snow.CreationTime),
Inline: false,
}
joinTime, _ := member.JoinedAt.Parse()
embed := &discordgo.MessageEmbed{
Title: title,
Description: fmt.Sprintf("%v (%v) Has Joined the Server", member.User.Mention(), member.User.ID),
Color: 0x0cc56a,
Thumbnail: thumb,
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("Current Member Count: %v", guild.MemberCount),
IconURL: guild.IconURL(),
},
Timestamp: joinTime.Format(time.RFC3339),
Fields: []*discordgo.MessageEmbedField{field},
}
s.ChannelMessageSendEmbed(channelID, embed)
}
func OnGuildMemberRemoveLogging(s *discordgo.Session, member *discordgo.GuildMemberRemove) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnGuildMemberAddLogging", r)
}
}()
timeNow := time.Now()
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", member.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
}
guild, err := s.State.Guild(member.GuildID)
if err != nil {
log.Println(err)
return
}
var title string
if member.User.Bot {
title = "Bot Left"
} else {
title = "Member Left"
}
thumb := &discordgo.MessageEmbedThumbnail{
URL: member.User.AvatarURL(""),
}
desc := ""
al, err := s.GuildAuditLog(member.GuildID, "", "", 20, 1)
if err != nil {
log.Println(err)
} else {
for _, log := range al.AuditLogEntries {
if log.TargetID == member.User.ID {
int64ID, _ := strconv.ParseInt(log.ID, 10, 64)
logSnow := discord_utils.ParseSnowflake(int64ID)
if timeNow.Sub(logSnow.CreationTime).Seconds() <= 10 {
user, err := s.User(log.UserID)
if err == nil {
desc = fmt.Sprintf("%v (%v) was Kicked by: %v\nReason: %v", member.User.String(), member.User.ID, user.String(), log.Reason)
} else {
desc = fmt.Sprintf("%v (%v) was Kicked by: %v\nReason: %v", member.User.String(), member.User.ID, log.UserID, log.Reason)
}
break
}
}
}
}
if desc == "" {
desc = fmt.Sprintf("%v (%v) Has Left the Server", member.User.String(), member.User.ID)
}
embed := &discordgo.MessageEmbed{
Title: title,
Description: desc,
Color: 0xff9431,
Thumbnail: thumb,
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("Current Member Count: %v", guild.MemberCount),
IconURL: guild.IconURL(),
},
Timestamp: timeNow.Format(time.RFC3339),
}
s.ChannelMessageSendEmbed(channelID, embed)
}
func AddMemberToDatabase(s *discordgo.Session, m *discordgo.GuildMemberAdd) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in AddMemberToDatabase", r)
}
}()
queryString := `INSERT INTO users (id, banned, logging, is_active, is_staff, is_admin)
VALUES ($1, false, false, true, false, false)`
_, err := postgres.DB.Exec(queryString, m.User.ID)
if err != nil {
log.Println(fmt.Errorf("error inserting %s into database: %w", m.User.ID, err))
return
}
log.Printf("New User: %s\n", m.User.ID)
}
func MarkMemberInactive(s *discordgo.Session, m *discordgo.GuildMemberRemove) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in MarkMemberInactive")
}
}()
queryString := `UPDATE users SET is_active = false WHERE id = $1`
_, err := postgres.DB.Exec(queryString, m.User.ID)
if err != nil {
log.Println(fmt.Errorf("error marking %s as inactive: %w", m.User.ID, err))
return
}
log.Println("User left: %s")
}
+97
View File
@@ -0,0 +1,97 @@
package events
import (
"fmt"
"log"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/postgres"
)
func OnMessageUpdate(session *discordgo.Session, m *discordgo.MessageUpdate) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnMessageUpdate", r)
}
}()
msg := m.BeforeUpdate
if msg.Author.Bot {
return
}
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
}
channel, err := session.State.Channel(msg.ChannelID)
if err != nil {
log.Println(err)
return
}
embed := &discordgo.MessageEmbed{
Title: fmt.Sprintf("Message Edited: %v", msg.ID),
Description: fmt.Sprintf("**Before:** %v\n**After:** %v\nIn Channel: %v", msg.Content, m.Content, channel.Mention()),
Color: session.State.UserColor(msg.Author.ID, channelID),
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("Author: %v", msg.Author.String()),
IconURL: msg.Author.AvatarURL(""),
},
}
session.ChannelMessageSendEmbed(channelID, embed)
}
func OnMessageDelete(session *discordgo.Session, m *discordgo.MessageDelete) {
defer func() {
if r := recover(); r != nil {
log.Println("Recovered from panic in OnMessageDelete", r)
}
}()
msg := m.BeforeDelete
if msg == nil {
log.Printf("Message Deleted but the original message was not in my cache so we are ignoring it.\nMessage ID: %v\nGuild ID: %v\nChannel ID: %v\n", m.ID, m.GuildID, m.ChannelID)
return
}
if msg.Author.Bot {
return
}
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", msg.GuildID)
err := row.Scan(&channelID)
if err != nil || channelID == "" {
return
}
channel, err := session.State.Channel(msg.ChannelID)
if err != nil {
log.Println(err)
return
}
desc := ""
al, err := session.GuildAuditLog(msg.GuildID, "", "", 72, 1)
if err != nil {
log.Println(err)
} else {
for _, log := range al.AuditLogEntries {
if log.TargetID == msg.Author.ID && log.Options.ChannelID == msg.ChannelID {
user, err := session.User(log.UserID)
if err == nil {
desc = fmt.Sprintf("**Content:** %v\nIn Channel: %v\nDeleted By: %v", msg.Content, channel.Mention(), user.Mention())
}
break
}
}
}
if desc == "" {
desc = fmt.Sprintf("**Content:** %v\nIn Channel: %v", msg.Content, channel.Mention())
}
embed := &discordgo.MessageEmbed{
Title: fmt.Sprintf("Message Deleted: %v", msg.ID),
Description: desc,
Color: session.State.UserColor(msg.Author.ID, channelID),
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("Author: %v", msg.Author.String()),
IconURL: msg.Author.AvatarURL(""),
},
}
session.ChannelMessageSendEmbed(channelID, embed)
}
+134
View File
@@ -0,0 +1,134 @@
package events
import (
"fmt"
"log"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/goff/internal/postgres"
)
type Task struct {
ID int64
Type string
Content string
GuildID string
ChannelID string
UserID string
CreationTime time.Time
TriggerTime time.Time
}
func processTask(task *Task, s *discordgo.Session) {
query := "SELECT completed, processing from tasks where id = $1"
res, err := postgres.DB.Query(query, task.ID)
if err != nil {
log.Println(err)
return
}
var completed bool
var processing bool
res.Next()
err = res.Scan(&completed, &processing)
if err != nil {
log.Println(err)
return
}
if completed || processing {
return
}
closeQuery := "Update tasks set completed = true where id = $1"
processQuery := "UPDATE tasks SET processing = true WHERE id = $1"
defer postgres.DB.Exec(closeQuery, task.ID)
_, err = postgres.DB.Exec(processQuery, task.ID)
if err != nil {
log.Println(err)
return
}
log.Println(fmt.Sprintf("Processing task %v", task.ID))
guild, err := s.Guild(task.GuildID)
if err != nil {
log.Print(fmt.Sprintf("Can't find guild with ID %v. Canceling task %v.", task.GuildID, task.ID))
return
}
channel, err := s.Channel(task.ChannelID)
if err != nil {
log.Print(fmt.Sprintf("Can't find channel with ID %v. Canceling task %v.", task.ChannelID, task.ID))
return
}
if channel.GuildID != guild.ID {
log.Print(fmt.Sprintf("The channel %v is not in guild %v. Canceling task %v.", channel.Name, guild.Name, task.ID))
return
}
member, err := s.GuildMember(guild.ID, task.UserID)
if err != nil {
log.Print(fmt.Sprintf("Can't find user with ID %v in guild %v. Canceling task %v.", task.UserID, guild.Name, task.ID))
return
}
if task.Type == "Reminder" {
color := s.State.UserColor(member.User.ID, channel.ID)
e := discordgo.MessageEmbed{
Title: "REMINDER",
Description: task.Content,
Timestamp: task.CreationTime.Format(time.RFC3339),
Color: color,
Footer: &discordgo.MessageEmbedFooter{
Text: "Created: ",
},
}
msg := discordgo.MessageSend{
Content: member.Mention(),
Embed: &e,
}
_, err = s.ChannelMessageSendComplex(channel.ID, &msg)
if err != nil {
log.Println(err)
}
}
processQuery = "UPDATE tasks SET processing = false WHERE id = $1"
_, err = postgres.DB.Exec(processQuery, task.ID)
if err != nil {
log.Println(err)
}
}
func getTasksToRun() []Task {
query := "SELECT id, type, content, guild_id, channel_id, user_id, creation_time, trigger_time " +
"from tasks where completed is false and processing is false and trigger_time < $1"
res, err := postgres.DB.Query(query, time.Now())
if err != nil {
log.Println(err)
}
var tasks []Task
for res.Next() {
var t Task
err = res.Scan(&t.ID, &t.Type, &t.Content, &t.GuildID, &t.ChannelID, &t.UserID, &t.CreationTime, &t.TriggerTime)
if err != nil {
log.Println(err)
}
for _, task := range tasks {
if task.ID == t.ID {
continue
}
}
tasks = append(tasks, t)
}
return tasks
}
func ProcessTasks(s *discordgo.Session, interval int) {
for {
time.Sleep(time.Duration(interval * 1e9))
tasks := getTasksToRun()
if len(tasks) > 0 {
for _, t := range tasks {
go processTask(&t, s)
}
}
}
}
+85
View File
@@ -0,0 +1,85 @@
package exts
import (
"errors"
"fmt"
"strings"
"github.com/dustinpianalto/disgoman"
)
func pCommand(ctx disgoman.Context, args []string) {
input := strings.Join(args, "")
const LENGTH = 1999
var mem [LENGTH]byte
pointer := 0
l := 0
for i := 0; i < len(input); i++ {
if input[i] == 'L' {
if pointer == 0 {
pointer = LENGTH - 1
} else {
pointer--
}
} else if input[i] == 'R' {
if pointer == LENGTH-1 {
pointer = 0
} else {
pointer++
}
} else if input[i] == '+' {
mem[pointer]++
} else if input[i] == '-' {
mem[pointer]--
} else if input[i] == '(' {
if mem[pointer] == 0 {
i++
for l > 0 || input[i] != ')' {
if input[i] == '(' {
l++
}
if input[i] == ')' {
l--
}
i++
}
}
} else if input[i] == ')' {
if mem[pointer] != 0 {
i--
for l > 0 || input[i] != '(' {
if input[i] == ')' {
l++
}
if input[i] == '(' {
l--
}
i--
}
}
} else {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Invalid Character: %v", input[i]),
Error: errors.New("invalid character"),
}
return
}
}
var out []byte
for _, i := range mem {
if i != 0 {
out = append(out, i)
}
}
_, err := ctx.Send(string(out))
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send results",
Error: err,
}
return
}
return
}
+84
View File
@@ -0,0 +1,84 @@
package exts
import (
"fmt"
"strconv"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/rpnparse"
)
func interleave(ctx disgoman.Context, args []string) {
if len(args) == 2 {
x, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
y, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
return
}
var z = int64(0)
for i := 0; i < 64; i++ {
x_masked_i := x & (1 << i)
y_masked_i := y & (1 << i)
z |= x_masked_i << i
z |= y_masked_i << (i + 1)
}
ctx.Send(fmt.Sprintf("%v", z))
}
}
func deinterleave(ctx disgoman.Context, args []string) {
if len(args) == 1 {
z, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
return
}
var x = int64(0)
var y = int64(0)
i := 0
for z > 0 {
x |= (z & 1) << i
z >>= 1
y |= (z & 1) << i
z >>= 1
i++
}
ctx.Send(fmt.Sprintf("(%v, %v)", x, y))
}
}
func generateRPNCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(rpn)
}
func parseRPNCommand(ctx disgoman.Context, args []string) {
res, err := rpnparse.ParseRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}
func solveCommand(ctx disgoman.Context, args []string) {
rpn, err := rpnparse.GenerateRPN(args)
if err != nil {
ctx.Send(err.Error())
return
}
res, err := rpnparse.ParseRPN(strings.Split(rpn, " "))
if err != nil {
ctx.Send(err.Error())
return
}
ctx.Send(fmt.Sprintf("The result is: %v", res))
}
+376
View File
@@ -0,0 +1,376 @@
package exts
import (
"database/sql"
"fmt"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/postgres"
)
// Guild management commands
func loggingChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET logging_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET logging_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Logging Channel Updated.")
}
func getLoggingChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT logging_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The logging channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The logging channel is currently %s", channel.Mention()))
return
}
func welcomeChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET welcome_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcomer Disabled.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET welcome_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Welcome Channel Updated.")
return
}
func getWelcomeChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT welcome_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The welcomer is disabled.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The welcome channel is currently %s", channel.Mention()))
}
func addGuildCommand(ctx disgoman.Context, args []string) {
var guildID string
row := postgres.DB.QueryRow("SELECT id FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&guildID)
if err == nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "This guild is already in my database",
Error: err,
}
return
}
_, err = postgres.DB.Query("INSERT INTO guilds (id) VALUES ($1)", ctx.Guild.ID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem inserting this guild into the database",
Error: err,
}
return
}
_, _ = ctx.Send("This guild has been added.")
}
func puzzleChannel(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
idString = idString[2 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET puzzle_channel='' WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
return
}
channel, err := ctx.Session.State.Channel(idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that channel.",
Error: err,
}
return
}
if channel.GuildID != ctx.Guild.ID {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "The channel passed is not in this guild.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET puzzle_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Channel Updated.")
}
func getPuzzleChannel(ctx disgoman.Context, _ []string) {
var channelID string
row := postgres.DB.QueryRow("SELECT puzzle_channel FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if channelID == "" {
_, _ = ctx.Send("The puzzle channel is not set.")
return
}
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The puzzle channel is currently %s", channel.Mention()))
return
}
func puzzleRole(ctx disgoman.Context, args []string) {
var idString string
if len(args) > 0 {
idString = args[0]
if strings.HasPrefix(idString, "<@&") && strings.HasSuffix(idString, ">") {
idString = idString[3 : len(idString)-1]
}
} else {
idString = ""
}
fmt.Println(idString)
if idString == "" {
_, err := postgres.DB.Exec("UPDATE guilds SET puzzle_role=NULL WHERE id=$1;", ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Role Cleared.")
return
}
role, err := ctx.Session.State.Role(ctx.Guild.ID, idString)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id) VALUES ($1, $2) ON CONFLICT DO NOTHING", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, err = postgres.DB.Exec("UPDATE guilds SET puzzle_role=$1 WHERE id=$2;", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send("Puzzle Role Updated.")
}
func getPuzzleRole(ctx disgoman.Context, _ []string) {
var roleID sql.NullString
row := postgres.DB.QueryRow("SELECT puzzle_role FROM guilds where id=$1", ctx.Guild.ID)
err := row.Scan(&roleID)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error getting data from the database.",
Error: err,
}
return
}
if !roleID.Valid {
_, _ = ctx.Send("The puzzle role is not set.")
return
}
role, err := ctx.Session.State.Role(ctx.Guild.ID, roleID.String)
if err != nil {
fmt.Println(err)
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got the role ID but it does not appear to be a valid role in this guild.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("The puzzle role is currently %s", role.Mention()))
return
}
+289
View File
@@ -0,0 +1,289 @@
package exts
import (
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff"
)
func AddCommandHandlers(h *goff.CommandManager) {
// Arguments:
// name - command name - string
// desc - command description - string
// owneronly - only allow owners to run - bool
// hidden - hide command from non-owners - bool
// perms - permissisions required - anpan.Permission (int)
// type - command type, sets where the command is available
// run - function to run - func(anpan.Context, []string) / CommandRunFunc
_ = h.AddCommand(&disgoman.Command{
Name: "ping",
Aliases: []string{" "},
Description: "Check the bot's ping",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pingCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "say",
Aliases: nil,
Description: "Repeat a message",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: sayCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "user",
Aliases: nil,
Description: "Get user info",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: userCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "git",
Aliases: nil,
Description: "Show my github link",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: gitCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "tag",
Aliases: nil,
Description: "Get a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: tagCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "addtag",
Aliases: nil,
Description: "Add a tag",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
SanitizeEveryone: true,
Invoke: addTagCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "invite",
Aliases: nil,
Description: "Get the invite link for this bot or others",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: inviteCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "P",
Aliases: nil,
Description: "Interpret a P\" program and return the results",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: pCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-logging-channel",
Aliases: []string{"slc"},
Description: "Set the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: loggingChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-logging-channel",
Aliases: []string{"glc"},
Description: "Gets the channel logging messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getLoggingChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-welcome-channel",
Aliases: []string{"swc"},
Description: "Set the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: welcomeChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-welcome-channel",
Aliases: []string{"gwc"},
Description: "Gets the channel welcome messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getWelcomeChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "kick",
Aliases: nil,
Description: "Kicks the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionKickMembers,
Invoke: kickUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "addGuild",
Aliases: nil,
Description: "Adds the current guild to the database",
OwnerOnly: true,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: addGuildCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "ban",
Aliases: []string{"ban-no-delete"},
Description: "Bans the given user with the given reason",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: banUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "unban",
Aliases: nil,
Description: "Unbans the given user",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionBanMembers,
Invoke: unbanUserCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "remind",
Aliases: nil,
Description: "Remind me at a later time",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: addReminderCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "encode",
Aliases: []string{"e"},
Description: "Encode 2 numbers",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: interleave,
})
_ = h.AddCommand(&disgoman.Command{
Name: "decode",
Aliases: []string{"d"},
Description: "Decode 1 number into 2",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: deinterleave,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-puzzle-channel",
Aliases: []string{"spc"},
Description: "Set the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: puzzleChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-puzzle-channel",
Aliases: []string{"gpc"},
Description: "Gets the channel puzzle messages will be sent to.",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleChannel,
})
_ = h.AddCommand(&disgoman.Command{
Name: "set-puzzle-role",
Aliases: []string{"spr"},
Description: "Set the role to be pinged when there is a new puzzle",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: puzzleRole,
})
_ = h.AddCommand(&disgoman.Command{
Name: "get-puzzle-role",
Aliases: []string{"gpr"},
Description: "Get the role that will be pinged when there is a new puzzle",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: getPuzzleRole,
})
_ = h.AddCommand(&disgoman.Command{
Name: "RPN",
Aliases: []string{"rpn"},
Description: "Convert infix to rpn",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: generateRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "ParseRPN",
Aliases: []string{"PRPN", "prpn"},
Description: "Parse RPN string and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: parseRPNCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "solve",
Aliases: []string{"math", "infix"},
Description: "Solve infix equation and return the result",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: solveCommand,
})
_ = h.AddCommand(&disgoman.Command{
Name: "make-role-self-assignable",
Aliases: []string{"makesar"},
Description: "Makes the passed in role self assignable by anyone",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: makeRoleSelfAssignable,
})
_ = h.AddCommand(&disgoman.Command{
Name: "remove-self-assignable-role",
Aliases: []string{"removesar"},
Description: "Makes a role that was previously self assignable not so",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: disgoman.PermissionManageServer,
Invoke: removeSelfAssignableRole,
})
_ = h.AddCommand(&disgoman.Command{
Name: "giverole",
Aliases: []string{"iwant", "givetome"},
Description: "Assigns a person the passed in role if it is self assignable",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: selfAssignRole,
})
_ = h.AddCommand(&disgoman.Command{
Name: "removerole",
Aliases: []string{"idon'twant"},
Description: "Removes a role from a person if the role is self assignable",
OwnerOnly: false,
Hidden: false,
RequiredPermissions: 0,
Invoke: unAssignRole,
})
}
+216
View File
@@ -0,0 +1,216 @@
package exts
import (
"fmt"
"strconv"
"strings"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/postgres"
)
func makeRoleSelfAssignable(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id, self_assignable) VALUES ($1, $2, true) ON CONFLICT (id) DO UPDATE SET self_assignable=true", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("%s is now self assignable", role.Name))
}
func removeSelfAssignableRole(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var err error
var role *discordgo.Role
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
_, err = postgres.DB.Exec("INSERT INTO roles (id, guild_id, self_assignable) VALUES ($1, $2, false) ON CONFLICT (id) DO UPDATE SET self_assignable=false", role.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("%s's self assignability has been removed.", role.Name))
}
func selfAssignRole(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
if memberHasRole(ctx.Member, role.ID) {
_, _ = ctx.Send(fmt.Sprintf("You already have the %s role silly...", role.Name))
return
}
var selfAssignable bool
err = postgres.DB.QueryRow("SELECT self_assignable FROM roles where id=$1", role.ID).Scan(&selfAssignable)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
if !selfAssignable {
_, _ = ctx.Send(fmt.Sprintf("You aren't allowed to assign yourself the %s role", role.Name))
return
}
err = ctx.Session.GuildMemberRoleAdd(ctx.Guild.ID, ctx.User.ID, role.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem adding that role to you.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("Congratulations! The %s role has been added to your... Ummm... Thing.", role.Name))
}
func unAssignRole(ctx disgoman.Context, args []string) {
var roleString string
var roleID string
if len(args) > 0 {
roleString = strings.Join(args, " ")
if strings.HasPrefix(roleString, "<@&") && strings.HasSuffix(roleString, ">") {
roleID = roleString[3 : len(roleString)-1]
} else if _, err := strconv.Atoi(roleString); err == nil {
roleID = roleString
} else {
for _, role := range ctx.Guild.Roles {
if roleString == role.Name {
roleID = role.ID
}
}
}
}
fmt.Println(roleID)
var role *discordgo.Role
var err error
if role, err = ctx.Session.State.Role(ctx.Guild.ID, roleID); err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Can't find that Role.",
Error: err,
}
return
}
if !memberHasRole(ctx.Member, role.ID) {
_, _ = ctx.Send(fmt.Sprintf("I can't remove the %s role from you because you don't have it...", role.Name))
return
}
var selfAssignable bool
err = postgres.DB.QueryRow("SELECT self_assignable FROM roles where id=$1", role.ID).Scan(&selfAssignable)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error Updating Database",
Error: err,
}
return
}
if !selfAssignable {
_, _ = ctx.Send(fmt.Sprintf("You aren't allowed to remove the %s role from yourself", role.Name))
return
}
err = ctx.Session.GuildMemberRoleRemove(ctx.Guild.ID, ctx.User.ID, role.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "There was a problem removing that role from you.",
Error: err,
}
return
}
_, _ = ctx.Send(fmt.Sprintf("Sad to see you go... but the %s role has been removed.", role.Name))
}
func memberHasRole(m *discordgo.Member, id string) bool {
for _, r := range m.Roles {
if r == id {
return true
}
}
return false
}
+122
View File
@@ -0,0 +1,122 @@
package exts
import (
"errors"
"fmt"
"log"
"strings"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/postgres"
)
func addTagCommand(ctx disgoman.Context, input []string) {
if len(input) >= 1 {
queryString := `SELECT tags.id, tags.tag, tags.content from tags
WHERE tags.guild_id = $1
AND tags.tag = $2;`
row := postgres.DB.QueryRow(queryString, ctx.Guild.ID, input[0])
var dest string
if err := row.Scan(&dest); err != nil {
tag := input[0]
if tag == "" {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "That is not a valid tag name",
Error: err,
}
return
}
if len(input) <= 1 {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I got a name but no value",
Error: err,
}
return
}
value := strings.Join(input[1:], " ")
if value == "" {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You have to include a content for the tag",
Error: err,
}
return
}
queryString = `INSERT INTO tags (tag, content, creator, guild_id) VALUES ($1, $2, $3, $4);`
_, err := postgres.DB.Exec(queryString, tag, value, ctx.Message.Author.ID, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "",
Error: err,
}
return
}
ctx.Send(fmt.Sprintf("Tag %v added successfully.", tag))
return
} else {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "That tag already exists",
Error: err,
}
return
}
} else {
ctx.Send("You need to tell me what tag you want to add...")
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You need to tell me what tag you want to add...",
Error: errors.New("nothing to do"),
}
return
}
}
func tagCommand(ctx disgoman.Context, args []string) {
if len(args) >= 1 {
tagString := strings.Join(args, " ")
queryString := `SELECT tags.id, tags.tag, tags.content from tags
WHERE tags.guild_id = $1;`
rows, err := postgres.DB.Query(queryString, ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "",
Error: err,
}
return
} else {
for rows.Next() {
var (
id int
tag string
content string
)
if err := rows.Scan(&id, &tag, &content); err != nil {
log.Println(err)
}
if tagString == tag {
ctx.Send(content)
return
}
}
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Tag %v not found", args[0]),
Error: err,
}
return
}
} else {
ctx.Send("I need a tag to fetch...")
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I need a tag to fetch...",
Error: errors.New("nothing to do"),
}
return
}
}
+56
View File
@@ -0,0 +1,56 @@
package exts
import (
"errors"
"fmt"
"strings"
"time"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/postgres"
"github.com/olebedev/when"
"github.com/olebedev/when/rules/common"
"github.com/olebedev/when/rules/en"
)
func addReminderCommand(ctx disgoman.Context, args []string) {
w := when.New(nil)
w.Add(en.All...)
w.Add(common.All...)
text := strings.Join(args, " ")
r, err := w.Parse(text, time.Now())
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error parsing time",
Error: err,
}
return
}
if r == nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You need to include a valid time",
Error: errors.New("no time found"),
}
return
}
content := strings.Replace(text, r.Text+" ", "", 1)
query := "INSERT INTO tasks (type, content, guild_id, channel_id, user_id, trigger_time) " +
"VALUES ('Reminder', $1, $2, $3, $4, $5)"
_, err = postgres.DB.Exec(query, content, ctx.Guild.ID, ctx.Channel.ID, ctx.User.ID, r.Time)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error adding task to database",
Error: err,
}
return
}
_ = ctx.Session.MessageReactionAdd(ctx.Channel.ID, ctx.Message.ID, "✅")
_, _ = ctx.Session.ChannelMessageSend(
ctx.Channel.ID,
fmt.Sprintf("I will remind you at %v, with `%v`", r.Time.Format(time.RFC1123), content),
)
}
+256
View File
@@ -0,0 +1,256 @@
package exts
import (
"errors"
"fmt"
"strings"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/events"
)
func kickUserCommand(ctx disgoman.Context, args []string) {
var member *discordgo.Member
var err error
if len(ctx.Message.Mentions) > 0 {
member, err = ctx.Session.GuildMember(ctx.Guild.ID, ctx.Message.Mentions[0].ID)
} else if len(args) >= 1 {
idString := args[0]
if strings.HasPrefix(idString, "<@!") && strings.HasSuffix(idString, ">") {
idString = idString[3 : len(idString)-1]
}
member, err = ctx.Session.GuildMember(ctx.Guild.ID, idString)
} else {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that member",
Error: err,
}
return
}
if higher, _ := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Message.Author.ID, member.User.ID); !higher {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You must have a higher role than the person you are trying to kick",
Error: errors.New("need higher role"),
}
return
}
if higher, _ := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Session.State.User.ID, member.User.ID); !higher {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I don't have a high enough role to kick that person",
Error: errors.New("need higher role"),
}
return
}
var reason string
if len(args) > 1 {
reason = strings.Join(args[1:], " ")
} else {
reason = "No Reason Given"
}
auditReason := fmt.Sprintf("%v#%v: %v", ctx.User.Username, ctx.User.Discriminator, reason)
err = ctx.Session.GuildMemberDeleteWithReason(ctx.Guild.ID, member.User.ID, auditReason)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong kicking %v", member.User.Username),
Error: err,
}
return
}
event := &events.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Kicked",
Description: fmt.Sprintf(
"User %v#%v was kicked by %v.\nReason: %v",
member.User.Username,
member.User.Discriminator,
ctx.Message.Author.Username,
reason),
Timestamp: time.Now().Format("2006-01-02 15:04:05"),
Color: 0xff8c00,
},
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
events.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been kicked.", member.User.Username, member.User.Discriminator))
}
func banUserCommand(ctx disgoman.Context, args []string) {
var user *discordgo.User
var err error
if len(ctx.Message.Mentions) > 0 {
user, err = ctx.Session.User(ctx.Message.Mentions[0].ID)
} else if len(args) >= 1 {
idString := args[0]
if strings.HasPrefix(idString, "<@!") && strings.HasSuffix(idString, ">") {
idString = idString[3 : len(idString)-1]
}
user, err = ctx.Session.User(idString)
} else {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that user",
Error: err,
}
return
}
if higher, err := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Message.Author.ID, user.ID); err != nil {
if err.Error() == "can't find caller member" {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Who are you?",
Error: err,
}
return
}
} else if !higher {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "You must have a higher role than the person you are trying to ban",
Error: errors.New("need higher role"),
}
return
}
if higher, err := disgoman.HasHigherRole(ctx.Session, ctx.Guild.ID, ctx.Session.State.User.ID, user.ID); err != nil {
if err.Error() == "can't find caller member" {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Who am I?",
Error: err,
}
return
}
} else if !higher {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "I don't have a high enough role to ban that person",
Error: errors.New("need higher role"),
}
return
}
var reason string
if len(args) > 1 {
reason = strings.Join(args[1:], " ")
} else {
reason = "No Reason Given"
}
auditReason := fmt.Sprintf("%v#%v: %v", ctx.User.Username, ctx.User.Discriminator, reason)
days := 7
if ctx.Invoked == "ban-no-delete" {
days = 0
}
err = ctx.Session.GuildBanCreateWithReason(ctx.Guild.ID, user.ID, auditReason, days)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong banning %v", user.Username),
Error: err,
}
return
}
event := &events.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Banned",
Description: fmt.Sprintf(
"User %v#%v was banned by %v.\nReason: %v",
user.Username,
user.Discriminator,
ctx.Message.Author.Username,
reason),
Timestamp: time.Now().Format("2006-01-02 15:04:05"),
Color: 0xff0000,
},
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
events.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been banned.", user.Username, user.Discriminator))
}
func unbanUserCommand(ctx disgoman.Context, args []string) {
var user *discordgo.User
var err error
if len(ctx.Message.Mentions) > 0 {
user, err = ctx.Session.User(ctx.Message.Mentions[0].ID)
} else if len(args) >= 1 {
idString := args[0]
if strings.HasPrefix(idString, "<@!") && strings.HasSuffix(idString, ">") {
idString = idString[3 : len(idString)-1]
}
user, err = ctx.Session.User(idString)
} else {
err = errors.New("that is not a valid id")
}
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that user",
Error: err,
}
return
}
bans, err := ctx.Session.GuildBans(ctx.Guild.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Error processing current bans",
Error: err,
}
return
}
for _, ban := range bans {
if ban.User.ID == user.ID {
err = ctx.Session.GuildBanDelete(ctx.Guild.ID, user.ID)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: fmt.Sprintf("Something went wrong unbanning %v", user.Username),
Error: err,
}
return
}
event := &events.LogEvent{
Embed: discordgo.MessageEmbed{
Title: "User Banned",
Description: fmt.Sprintf(
"User %v#%v was unbanned by %v.\nOrignal Ban Reason: %v",
user.Username,
user.Discriminator,
ctx.Message.Author.Username,
ban.Reason),
Timestamp: time.Now().Format("2006-01-02 15:04:05"),
Color: 0x00ff00,
},
GuildID: ctx.Guild.ID,
Session: ctx.Session,
}
events.LoggingChannel <- event
_, _ = ctx.Send(fmt.Sprintf("User %v#%v has been unbanned.", user.Username, user.Discriminator))
return
}
}
_, _ = ctx.Send(fmt.Sprintf("%v#%v is not banned in this guild.", user.Username, user.Discriminator))
}
+169
View File
@@ -0,0 +1,169 @@
package exts
import (
"fmt"
"sort"
"strconv"
"strings"
"time"
"github.com/bwmarrin/discordgo"
"github.com/dustinpianalto/disgoman"
"github.com/dustinpianalto/goff/internal/discord_utils"
)
func pingCommand(ctx disgoman.Context, _ []string) {
timeBefore := time.Now()
msg, _ := ctx.Send("Pong!")
took := time.Now().Sub(timeBefore)
_, err := ctx.Session.ChannelMessageEdit(ctx.Message.ChannelID, msg.ID, fmt.Sprintf("Pong!\nPing Took **%s**", took.String()))
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Ping Failed",
Error: err,
}
}
}
func inviteCommand(ctx disgoman.Context, args []string) {
var ids []string
if len(args) == 0 {
ids = []string{ctx.Session.State.User.ID}
} else {
for _, id := range args {
ids = append(ids, id)
}
}
for _, id := range ids {
url := fmt.Sprintf("<https://discordapp.com/oauth2/authorize?client_id=%v&scope=bot>", id)
_, err := ctx.Send(url)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send the invite link.",
Error: err,
}
}
}
}
func gitCommand(ctx disgoman.Context, _ []string) {
embed := &discordgo.MessageEmbed{
Title: "Hi there, My code is on Github",
Color: 0,
URL: "https://github.com/dustinpianalto/Goff",
}
_, err := ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Git failed",
Error: err,
}
}
}
func sayCommand(ctx disgoman.Context, args []string) {
resp := strings.Join(args, " ")
resp = strings.ReplaceAll(resp, "@everyone", "@\ufff0everyone")
resp = strings.ReplaceAll(resp, "@here", "@\ufff0here")
_, err := ctx.Session.ChannelMessageSend(ctx.Message.ChannelID, resp)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Say Failed",
Error: err,
}
}
}
func userCommand(ctx disgoman.Context, args []string) {
var member *discordgo.Member
if len(args) == 0 {
member, _ = ctx.Session.GuildMember(ctx.Guild.ID, ctx.Message.Author.ID)
} else {
var err error
if len(ctx.Message.Mentions) > 0 {
member, err = ctx.Session.GuildMember(ctx.Guild.ID, ctx.Message.Mentions[0].ID)
} else {
member, err = ctx.Session.GuildMember(ctx.Guild.ID, args[0])
}
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't get that member",
Error: err,
}
return
}
}
thumb := &discordgo.MessageEmbedThumbnail{
URL: member.User.AvatarURL(""),
}
var botString string
if member.User.Bot {
botString = "BOT"
} else {
botString = ""
}
var roles []*discordgo.Role
for _, roleID := range member.Roles {
role, _ := ctx.Session.State.Role(ctx.Guild.ID, roleID)
roles = append(roles, role)
}
sort.Slice(roles, func(i, j int) bool { return roles[i].Position > roles[j].Position })
var roleMentions []string
for _, role := range roles {
roleMentions = append(roleMentions, role.Mention())
}
var rolesString string
if len(roleMentions) > 0 {
rolesString = strings.Join(roleMentions, " ")
} else {
rolesString = "None"
}
rolesField := &discordgo.MessageEmbedField{
Name: "Roles:",
Value: rolesString,
Inline: false,
}
guildJoinTime, _ := member.JoinedAt.Parse()
guildJoinedField := &discordgo.MessageEmbedField{
Name: "Joined Guild:",
Value: discord_utils.ParseDateString(guildJoinTime),
Inline: false,
}
int64ID, _ := strconv.ParseInt(member.User.ID, 10, 64)
s := discord_utils.ParseSnowflake(int64ID)
discordJoinedField := &discordgo.MessageEmbedField{
Name: "Joined Discord:",
Value: discord_utils.ParseDateString(s.CreationTime),
Inline: false,
}
embed := &discordgo.MessageEmbed{
Title: fmt.Sprintf("%v#%v %v", member.User.Username, member.User.Discriminator, botString),
Description: fmt.Sprintf("**%v** (%v)", member.Nick, member.User.ID),
Color: ctx.Session.State.UserColor(member.User.ID, ctx.Channel.ID),
Thumbnail: thumb,
Fields: []*discordgo.MessageEmbedField{
guildJoinedField,
discordJoinedField,
rolesField,
},
}
_, err := ctx.Session.ChannelMessageSendEmbed(ctx.Channel.ID, embed)
if err != nil {
ctx.CommandManager.ErrorChannel <- disgoman.CommandError{
Context: ctx,
Message: "Couldn't send the user embed",
Error: err,
}
}
}
+157
View File
@@ -0,0 +1,157 @@
package postgres
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
var (
DB *sql.DB
)
func ConnectDatabase(dbConnString string) {
db, err := sql.Open("postgres", dbConnString)
if err != nil {
panic(fmt.Sprintf("Can't connect to the database. %v", err))
} else {
fmt.Println("Database Connected.")
}
db.SetMaxOpenConns(75) // The RDS instance has a max of 75 open connections
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(300)
DB = db
}
func InitializeDatabase() {
_, err := DB.Query("CREATE TABLE IF NOT EXISTS users(" +
"id varchar(30) primary key," +
"banned bool not null default false," +
"logging bool not null default true," +
"steam_id varchar(30) NOT NULL DEFAULT ''," +
"is_active bool not null default true," +
"is_staff bool not null default false," +
"is_admin bool not null default false" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS guilds(" +
"id varchar(30) primary key," +
"welcome_message varchar(1000) NOT NULL DEFAULT ''," +
"goodbye_message varchar(1000) NOT NULL DEFAULT ''," +
"logging_channel varchar(30) NOT NULL DEFAULT ''," +
"welcome_channel varchar(30) NOT NULL DEFAULT ''" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS prefixes(" +
"id serial primary key," +
"prefix varchar(10) not null unique default 'Go.'" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS tags(" +
"id serial primary key," +
"tag varchar(100) not null unique," +
"content varchar(1000) not null," +
"creator varchar(30) not null references users(id)," +
"creation_time timestamp not null default NOW()," +
"guild_id varchar(30) not null references guilds(id)" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS x_users_guilds(" +
"guild_id varchar(30) not null references guilds(id)," +
"user_id varchar(30) not null references users(id)" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS x_guilds_prefixes(" +
"guild_id varchar(30) not null references guilds(id)," +
"prefix_id int not null references prefixes(id)" +
")")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("CREATE TABLE IF NOT EXISTS tasks(" +
"id serial primary key," +
"type varchar(10) not null," +
"content text not null," +
"guild_id varchar(30) not null references guilds(id)," +
"channel_id varchar(30) not null," +
"user_id varchar(30) not null," +
"creation_time timestamp not null default NOW()," +
"trigger_time timestamp not null," +
"completed bool not null default false," +
"processing bool default false)")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query(`CREATE TABLE IF NOT EXISTS postfixes(
id serial primary key,
name varchar(100) not null,
time timestamp not null default NOW())`)
if err != nil {
log.Println(err)
}
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS puzzles(
id serial primary key,
text text not null,
time timestamp not null
)`)
if err != nil {
log.Println(err)
}
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS x_guilds_puzzles(
id serial primary key,
guild_id varchar(30) not null references guilds(id),
puzzle_id int not null references puzzles(id),
message_id varchar(30) not null
)`)
RunPostfixes()
}
func LoadTestData() {
_, err := DB.Query("INSERT INTO users (id, banned, logging, steam_id, is_active, is_staff, is_admin) values " +
"('351794468870946827', false, true, '76561198024193239', true, true, true)," +
"('692908139506434065', false, true, '', true, false, false)," +
"('396588996706304010', false, true, '', true, true, false)")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("INSERT INTO guilds (id, welcome_message, goodbye_message) VALUES " +
"('265828729970753537', 'Hey there is someone new here.', 'Well fine then... Just leave without saying goodbye')")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("INSERT INTO prefixes (prefix) VALUES ('Godev.'), ('godev.'), ('godev,')")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("INSERT INTO x_users_guilds (guild_id, user_id) VALUES " +
"('265828729970753537', '351794468870946827')," +
"('265828729970753537', '692908139506434065')," +
"('265828729970753537', '396588996706304010')")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("INSERT INTO x_guilds_prefixes (guild_id, prefix_id) VALUES " +
"('265828729970753537', 1)," +
"('265828729970753537', 2)," +
"('265828729970753537', 3)")
if err != nil {
fmt.Println(err)
}
_, err = DB.Query("INSERT INTO tags (tag, content, creator, guild_id) VALUES " +
"('test', 'This is a test of the tag system', '351794468870946827', '265828729970753537')")
if err != nil {
fmt.Println(err)
}
}
+65
View File
@@ -0,0 +1,65 @@
package postgres
import (
"database/sql"
"github.com/dustinpianalto/goff"
)
type GuildService struct {
DB *sql.DB
}
func (s *GuildService) Guild(id string) (*goff.Guild, error) {
var g goff.Guild
queryString := `SELECT id, welcome_message, goodbye_message,
logging_channel, welcome_channel, puzzle_channel, puzzle_role
FROM guilds
WHERE id = $1`
row := s.DB.QueryRow(queryString, id)
err := row.Scan(
&g.ID,
&g.WelcomeMessage,
&g.GoodbyeMessage,
&g.LoggingChannel,
&g.WelcomeChannel,
&g.PuzzleChannel,
&g.PuzzleRole,
)
if err != nil {
return nil, err
}
var prefixes []string
queryString = `SELECT p.prefix
FROM prefixes p, x_guilds_prefixes xgp
WHERE p.id = xgp.prefix_id AND xgp.guild_id = $1`
rows, err := s.DB.Query(queryString, id)
if err == nil {
for rows.Next() {
var prefix string
err = rows.Scan(&prefix)
if err != nil {
continue
}
prefixes = append(prefixes, prefix)
}
}
g.Prefixes = prefixes
return &g, nil
}
func (s *GuildService) CreateGuild(g *goff.Guild) error {
return nil
}
func (s *GuildService) DeleteGuild(g *goff.Guild) error {
return nil
}
func (s *GuildService) GuildUsers(g *goff.Guild) ([]*goff.User, error) {
return []*goff.User{}, nil
}
func (s *GuildService) UpdateGuild(g *goff.Guild) error {
return nil
}
+164
View File
@@ -0,0 +1,164 @@
package postgres
import "log"
type postfix struct {
Name string
Invoke func(bool) error
}
var postfixes = []postfix{
postfix{
Name: "1_Update_Guild_for_Puzzle",
Invoke: updateGuildForPuzzle,
},
postfix{
Name: "1_Update_X_Guild_Prefixes_to_add_ID",
Invoke: updateXGuildPrefixesToAddID,
},
postfix{
Name: "1_Update_Tags_Content_Length",
Invoke: updateTagsContentLength,
},
postfix{
Name: "2_Add_Table_Roles",
Invoke: addTableRoles,
},
postfix{
Name: "3_Update_Guild_Add_Puzzle_Role",
Invoke: updateGuildsAddPuzzleRole,
},
postfix{
Name: "4_Add_Multi_Column_Unique_XUsersGuilds",
Invoke: addMultiColumnUniqueXUsersGuilds,
},
}
func RunPostfixes() {
for _, postfix := range postfixes {
queryString := "SELECT * from postfixes where name = $1"
rows, err := DB.Query(queryString, postfix.Name)
if err != nil {
log.Println(err)
continue
}
if rows.Next() {
continue
} else {
err := postfix.Invoke(false)
if err != nil {
continue
}
_, err = DB.Exec("INSERT INTO postfixes (name) VALUES ($1)", postfix.Name)
if err != nil {
log.Println(err)
continue
}
}
}
}
func updateGuildForPuzzle(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE guilds
ADD COLUMN puzzle_channel varchar(30) not null default ''`
} else {
queryString = `ALTER TABLE guilds
DROP COLUMN puzzleChat`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateXGuildPrefixesToAddID(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE x_guilds_prefixes
ADD COLUMN id serial primary key`
} else {
queryString = `ALTER TABLE x_guilds_prefixes
DROP COLUMN id`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateTagsContentLength(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE tags
ALTER COLUMN content TYPE varchar(2000)`
} else {
queryString = `ALTER TABLE tags
ALTER COLUMN content TYPE varchar(1000)`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func addTableRoles(revert bool) error {
var queryString string
if !revert {
queryString = `CREATE TABLE roles(
id varchar(30) primary key,
guild_id varchar(30) not null references guilds(id),
self_assignable bool not null default false,
admin bool not null default false,
moderator bool not null default false
)`
} else {
queryString = `DROP TABLE roles`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func updateGuildsAddPuzzleRole(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE guilds
ADD COLUMN puzzle_role varchar(30) references roles(id)`
} else {
queryString = `ALTER TABLE guilds
DROP COLUMN puzzle_role`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
func addMultiColumnUniqueXUsersGuilds(revert bool) error {
var queryString string
if !revert {
queryString = `ALTER TABLE x_users_guilds
ADD CONSTRAINT u_user_guild UNIQUE(user_id, guild_id)`
} else {
queryString = `ALTER TABLE DROP CONSTRAINT u_user_guild IF EXISTS`
}
_, err := DB.Exec(queryString)
if err != nil {
log.Println(err)
return err
}
return nil
}
+84
View File
@@ -0,0 +1,84 @@
package postgres
import (
"database/sql"
"github.com/dustinpianalto/goff"
)
type UserService struct {
DB *sql.DB
}
func (s *UserService) User(id string) (*goff.User, error) {
var u goff.User
queryString := `SELECT id, banned, logging, steam_id, is_active, is_staff, is_admin
FROM users WHERE id=$1`
row := s.DB.QueryRow(queryString, id)
if err := row.Scan(&u.ID, &u.Banned, &u.Logging, &u.SteamID, &u.IsActive, &u.IsStaff, &u.IsAdmin); err != nil {
return nil, err
}
var guilds []string
queryString = `SELECT guild_id from x_users_guilds WHERE user_id=$1`
rows, err := s.DB.Query(queryString, id)
if err != nil {
return nil, err
}
for rows.Next() {
var guildID string
err = rows.Scan(&guildID)
if err != nil {
return nil, err
}
guilds = append(guilds, guildID)
}
u.Guilds = guilds
return &u, nil
}
func (s *UserService) CreateUser(u *goff.User) error {
queryString := `INSERT INTO users (id, banned, logging, steam_id, is_active, is_staff, is_admin)
VALUES ($1, $2, $3, $4, $5, $6, $7)`
_, err := s.DB.Exec(queryString, u.ID, u.Banned, u.Logging, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
return err
}
func (s *UserService) DeleteUser(u *goff.User) error {
queryString := `DELETE FROM x_users_guilds WHERE user_id = $1; DELETE FROM users WHERE id = $1`
_, err := s.DB.Exec(queryString, u.ID)
return err
}
func (s *UserService) MarkUserInactive(u *goff.User) error {
queryString := `UPDATE users SET is_active = false WHERE id = $1`
_, err := s.DB.Exec(queryString, u.ID)
if err == nil {
u.IsActive = false
}
return err
}
func (s *UserService) AddUserToGuild(u *goff.User, g *goff.Guild) error {
queryString := `INSERT INTO x_users_guilds (user_id, guild_id) VALUES ($1, $2)`
_, err := s.DB.Exec(queryString, u.ID, g.ID)
return err
}
func (s *UserService) RemoveUserFromGuild(u *goff.User, g *goff.Guild) error {
queryString := `DELETE FROM x_users_guilds WHERE user_id = $1 AND guild_id = $2`
_, err := s.DB.Exec(queryString, u.ID, g.ID)
return err
}
func (s *UserService) UpdateUser(u *goff.User) error {
queryString := `UPDATE users SET
banned = $1
logging = $2
steam_id = $3
is_active = $4
is_staff = $5
is_admin = $6
WHERE id = $7`
_, err := s.DB.Exec(queryString, u.Banned, u.Logging, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin)
return err
}