diff --git a/app/http/endpoints/api/blacklist.go b/app/http/endpoints/api/blacklist.go index 00348aa..5f36d69 100644 --- a/app/http/endpoints/api/blacklist.go +++ b/app/http/endpoints/api/blacklist.go @@ -1,11 +1,14 @@ package api import ( + "context" "fmt" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/gin-gonic/gin" + "golang.org/x/sync/errgroup" "strconv" + "sync" ) type userData struct { @@ -16,18 +19,38 @@ type userData struct { func GetBlacklistHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - data := make(map[string]userData) - - blacklistedUsers := table.GetBlacklistNodes(guildId) - for _, row := range blacklistedUsers { - formattedId := strconv.FormatUint(row.User, 10) - user, _ := cache.Instance.GetUser(row.User) - - data[formattedId] = userData{ - Username: user.Username, - Discriminator: fmt.Sprintf("%04d", user.Discriminator), - } + blacklistedUsers, err := database.Client.Blacklist.GetBlacklistedUsers(guildId) + if err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return } + data := make(map[string]userData) + var lock sync.Mutex + + group, _ := errgroup.WithContext(context.Background()) + for _, userId := range blacklistedUsers { + group.Go(func() error { + user, _ := cache.Instance.GetUser(userId) + + lock.Lock() + + // JS cant do big ints + data[strconv.FormatUint(userId, 10)] = userData{ + Username: user.Username, + Discriminator: fmt.Sprintf("%04d", user.Discriminator), + } + + lock.Unlock() + + return nil + }) + } + + _ = group.Wait() + ctx.JSON(200, data) } diff --git a/app/http/endpoints/api/blacklistadd.go b/app/http/endpoints/api/blacklistadd.go index 852cdb5..bd3dd43 100644 --- a/app/http/endpoints/api/blacklistadd.go +++ b/app/http/endpoints/api/blacklistadd.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/gin-gonic/gin" "github.com/jackc/pgx/v4" @@ -50,11 +50,15 @@ func AddBlacklistHandler(ctx *gin.Context) { } // TODO: Don't blacklist staff or guild owner - - go table.AddBlacklist(guildId, targetId) - - ctx.JSON(200, gin.H{ - "success": true, - "user_id": strconv.FormatUint(targetId, 10), - }) + if err = database.Client.Blacklist.Add(guildId, targetId); err == nil { + ctx.JSON(200, gin.H{ + "success": true, + "user_id": strconv.FormatUint(targetId, 10), + }) + } else { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + } } diff --git a/app/http/endpoints/api/blacklistremove.go b/app/http/endpoints/api/blacklistremove.go index c6b28ed..02cf0c0 100644 --- a/app/http/endpoints/api/blacklistremove.go +++ b/app/http/endpoints/api/blacklistremove.go @@ -1,7 +1,7 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/gin-gonic/gin" "strconv" ) @@ -18,9 +18,14 @@ func RemoveBlacklistHandler(ctx *gin.Context) { return } - go table.RemoveBlacklist(guildId, userId) - - ctx.JSON(200, gin.H{ - "success": true, - }) + if err := database.Client.Blacklist.Remove(guildId, userId); err == nil { + ctx.JSON(200, gin.H{ + "success": true, + }) + } else { + ctx.JSON(200, gin.H{ + "success": false, + "err": err.Error(), + }) + } } diff --git a/app/http/endpoints/api/closeticket.go b/app/http/endpoints/api/closeticket.go index 51e1ae3..90aaea7 100644 --- a/app/http/endpoints/api/closeticket.go +++ b/app/http/endpoints/api/closeticket.go @@ -1,9 +1,10 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/messagequeue" "github.com/gin-gonic/gin" + "strconv" ) type closeBody struct { @@ -13,7 +14,15 @@ type closeBody struct { func CloseTicket(ctx *gin.Context) { userId := ctx.Keys["userid"].(uint64) guildId := ctx.Keys["guildid"].(uint64) - uuid := ctx.Param("uuid") + + ticketId, err := strconv.Atoi(ctx.Param("ticketId")) + if err != nil { + ctx.AbortWithStatusJSON(400, gin.H{ + "success": true, + "error": "Invalid ticket ID", + }) + return + } var data closeBody if err := ctx.BindJSON(&data); err != nil { @@ -24,12 +33,18 @@ func CloseTicket(ctx *gin.Context) { return } - // Verify that the ticket exists - ticketChan := make(chan table.Ticket) - go table.GetTicket(uuid, ticketChan) - ticket := <-ticketChan + // Get the ticket struct + ticket, err := database.Client.Tickets.Get(ticketId, guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": true, + "error": err.Error(), + }) + return + } - if ticket.Uuid == "" { + // Verify the ticket exists + if ticket.UserId == 0 { ctx.AbortWithStatusJSON(404, gin.H{ "success": true, "error": "Ticket does not exist", @@ -37,7 +52,7 @@ func CloseTicket(ctx *gin.Context) { return } - if ticket.Guild != guildId { + if ticket.GuildId != guildId { ctx.AbortWithStatusJSON(403, gin.H{ "success": true, "error": "Guild ID does not matched", @@ -45,7 +60,7 @@ func CloseTicket(ctx *gin.Context) { return } - go messagequeue.Client.PublishTicketClose(ticket.Uuid, userId, data.Reason) + go messagequeue.Client.PublishTicketClose(guildId, ticket.Id, userId, data.Reason) ctx.JSON(200, gin.H{ "success": true, diff --git a/app/http/endpoints/api/getticket.go b/app/http/endpoints/api/getticket.go index 698c656..cf1bfe3 100644 --- a/app/http/endpoints/api/getticket.go +++ b/app/http/endpoints/api/getticket.go @@ -3,7 +3,7 @@ package api import ( "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" @@ -18,13 +18,27 @@ var MentionRegex, _ = regexp.Compile("<@(\\d+)>") func GetTicket(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - uuid := ctx.Param("uuid") - ticketChan := make(chan table.Ticket) - go table.GetTicket(uuid, ticketChan) - ticket := <-ticketChan + ticketId, err := strconv.Atoi(ctx.Param("ticketId")) + if err != nil { + ctx.AbortWithStatusJSON(400, gin.H{ + "success": true, + "error": "Invalid ticket ID", + }) + return + } - if ticket.Guild != guildId { + // Get the ticket struct + ticket, err := database.Client.Tickets.Get(ticketId, guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": true, + "error": err.Error(), + }) + return + } + + if ticket.GuildId != guildId { ctx.AbortWithStatusJSON(403, gin.H{ "success": false, "error": "Guild ID doesn't match", @@ -32,7 +46,7 @@ func GetTicket(ctx *gin.Context) { return } - if !ticket.IsOpen { + if !ticket.Open { ctx.AbortWithStatusJSON(404, gin.H{ "success": false, "error": "Ticket does not exist", @@ -40,8 +54,16 @@ func GetTicket(ctx *gin.Context) { return } + if ticket.ChannelId == nil { + ctx.AbortWithStatusJSON(404, gin.H{ + "success": false, + "error": "Ticket channel does not exist", + }) + return + } + // Get messages - messages, _ := rest.GetChannelMessages(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.Channel, rest.GetChannelMessagesData{Limit: 100}) + messages, _ := rest.GetChannelMessages(config.Conf.Bot.Token, ratelimit.Ratelimiter, *ticket.ChannelId, rest.GetChannelMessagesData{Limit: 100}) // Format messages, exclude unneeded data messagesFormatted := make([]map[string]interface{}, 0) diff --git a/app/http/endpoints/api/gettickets.go b/app/http/endpoints/api/gettickets.go index 7329c7b..ec4b63e 100644 --- a/app/http/endpoints/api/gettickets.go +++ b/app/http/endpoints/api/gettickets.go @@ -1,48 +1,71 @@ package api import ( + "context" "fmt" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/gin-gonic/gin" + "golang.org/x/sync/errgroup" "strconv" - "strings" ) func GetTickets(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - tickets := table.GetOpenTickets(guildId) - ticketsFormatted := make([]map[string]interface{}, 0) - - for _, ticket := range tickets { - membersFormatted := make([]map[string]interface{}, 0) - for index, memberIdStr := range strings.Split(ticket.Members, ",") { - if memberId, err := strconv.ParseUint(memberIdStr, 10, 64); err == nil { - if memberId != 0 { - var separator string - if index != len(strings.Split(ticket.Members, ","))-1 { - separator = ", " - } - - member, _ := cache.Instance.GetUser(memberId) - membersFormatted = append(membersFormatted, map[string]interface{}{ - "username": member.Username, - "discrim": fmt.Sprintf("%04d", member.Discriminator), - "sep": separator, - }) - } - } - } - - owner, _ := cache.Instance.GetUser(ticket.Owner) - ticketsFormatted = append(ticketsFormatted, map[string]interface{}{ - "uuid": ticket.Uuid, - "ticketId": ticket.TicketId, - "username": owner.Username, - "discrim": fmt.Sprintf("%04d", owner.Discriminator), - "members": membersFormatted, + tickets, err := database.Client.Tickets.GetGuildOpenTickets(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), }) + return + } + + ticketsFormatted := make([]map[string]interface{}, len(tickets)) + + group, _ := errgroup.WithContext(context.Background()) + + for i, ticket := range tickets { + i := i + ticket := ticket + + group.Go(func() error { + members, err := database.Client.TicketMembers.Get(guildId, ticket.Id) + if err != nil { + return err + } + + membersFormatted := make([]map[string]interface{}, 0) + for _, userId := range members { + user, _ := cache.Instance.GetUser(userId) + + membersFormatted = append(membersFormatted, map[string]interface{}{ + "id": strconv.FormatUint(userId, 10), + "username": user.Username, + "discrim": fmt.Sprintf("%04d", user.Discriminator), + }) + } + + owner, _ := cache.Instance.GetUser(ticket.UserId) + + ticketsFormatted[len(tickets) - 1 - i] = map[string]interface{}{ + "ticketId": ticket.Id, + "username": owner.Username, + "discrim": fmt.Sprintf("%04d", owner.Discriminator), + "members": membersFormatted, + } + + return nil + }) + } + + if err := group.Wait(); err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return } ctx.JSON(200, ticketsFormatted) diff --git a/app/http/endpoints/api/guilds.go b/app/http/endpoints/api/guilds.go index f7d71a0..a49af30 100644 --- a/app/http/endpoints/api/guilds.go +++ b/app/http/endpoints/api/guilds.go @@ -1,28 +1,48 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/utils" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/objects/guild" ) +type wrappedGuild struct { + Id uint64 `json:"id,string"` + Name string `json:"name"` +} + func GetGuilds(ctx *gin.Context) { userId := ctx.Keys["userid"].(uint64) - userGuilds := table.GetGuilds(userId) - adminGuilds := make([]guild.Guild, 0) - for _, g := range userGuilds { + guilds, err := database.Client.UserGuilds.Get(userId) + if err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + adminGuilds := make([]wrappedGuild, 0) + for _, g := range guilds { fakeGuild := guild.Guild{ - Id: g.Id, - OwnerId: g.OwnerId, - Permissions: g.Permissions, + Id: g.GuildId, + Owner: g.Owner, + Permissions: int(g.UserPermissions), + } + + if g.Owner { + fakeGuild.OwnerId = userId } isAdmin := make(chan bool) go utils.IsAdmin(fakeGuild, userId, isAdmin) if <-isAdmin { - adminGuilds = append(adminGuilds, g) + adminGuilds = append(adminGuilds, wrappedGuild{ + Id: g.GuildId, + Name: g.Name, + }) } } diff --git a/app/http/endpoints/api/logslist.go b/app/http/endpoints/api/logslist.go index 9579096..4af0055 100644 --- a/app/http/endpoints/api/logslist.go +++ b/app/http/endpoints/api/logslist.go @@ -4,10 +4,11 @@ import ( "context" "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + dbclient "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/database" "github.com/apex/log" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" @@ -15,15 +16,15 @@ import ( ) const ( - pageLimit = 30 + pageLimit = 2 ) func GetLogs(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - page, err := strconv.Atoi(ctx.Param("page")) - if page < 1 { - page = 1 + before, err := strconv.Atoi(ctx.Query("before")) + if before < 0 { + before = 0 } // Get ticket ID from URL @@ -32,15 +33,20 @@ func GetLogs(ctx *gin.Context) { ticketId, _ = strconv.Atoi(ctx.Query("ticketid")) } - var tickets []table.Ticket + var tickets []database.Ticket // Get tickets from DB if ticketId > 0 { - ticketChan := make(chan table.Ticket) - go table.GetTicketById(guildId, ticketId, ticketChan) - ticket := <-ticketChan + ticket, err := dbclient.Client.Tickets.Get(ticketId, guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } - if ticket.Uuid != "" && !ticket.IsOpen { + if ticket.UserId != 0 && !ticket.Open { tickets = append(tickets, ticket) } } else { @@ -76,25 +82,27 @@ func GetLogs(ctx *gin.Context) { } if ctx.Query("userid") != "" || ctx.Query("username") != "" { - tickets = table.GetClosedTicketsByUserId(guildId, filteredIds) + tickets, err = dbclient.Client.Tickets.GetMemberClosedTickets(guildId, filteredIds, pageLimit, before) } else { - tickets = table.GetClosedTickets(guildId) + tickets, err = dbclient.Client.Tickets.GetGuildClosedTickets(guildId, pageLimit, before) + } + + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return } } // Select 30 logs + format them formattedLogs := make([]map[string]interface{}, 0) - for i := (page - 1) * pageLimit; i < (page-1)*pageLimit+pageLimit; i++ { - if i >= len(tickets) { - break - } - - ticket := tickets[i] - + for _, ticket := range tickets { // get username - user, found := cache.Instance.GetUser(ticket.Owner) + user, found := cache.Instance.GetUser(ticket.UserId) if !found { - user, err = rest.GetUser(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.Owner) + user, err = rest.GetUser(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.UserId) if err != nil { log.Error(err.Error()) } @@ -102,8 +110,8 @@ func GetLogs(ctx *gin.Context) { } formattedLogs = append(formattedLogs, map[string]interface{}{ - "ticketid": ticket.TicketId, - "userid": strconv.FormatUint(ticket.Owner, 10), + "ticketid": ticket.Id, + "userid": strconv.FormatUint(ticket.UserId, 10), "username": user.Username, }) } diff --git a/app/http/endpoints/api/modmaillogslist.go b/app/http/endpoints/api/modmaillogslist.go index 0b33087..c2bb8f9 100644 --- a/app/http/endpoints/api/modmaillogslist.go +++ b/app/http/endpoints/api/modmaillogslist.go @@ -3,9 +3,11 @@ package api import ( "context" "fmt" - "github.com/TicketsBot/GoPanel/database/table" + dbclient "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" + "github.com/TicketsBot/database" "github.com/gin-gonic/gin" + "github.com/gofrs/uuid" "regexp" "strconv" ) @@ -18,15 +20,18 @@ type wrappedModLog struct { UserId uint64 `json:"user_id,string"` } +// TODO: Take after param func GetModmailLogs(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - page, err := strconv.Atoi(ctx.Param("page")) + after, err := uuid.FromString(ctx.Query("after")) if err != nil { - ctx.AbortWithStatusJSON(400, gin.H{ - "success": false, - "error": err.Error(), - }) + after = uuid.Nil + } + + before, err := uuid.FromString(ctx.Query("before")) + if err != nil { + before = uuid.Nil } // filter @@ -53,27 +58,28 @@ func GetModmailLogs(ctx *gin.Context) { shouldFilter := userId > 0 - start := pageLimit * (page - 1) - end := start + pageLimit - 1 - wrapped := make([]wrappedModLog, 0) - var archives []table.ModMailArchive + var archives []database.ModmailArchive if shouldFilter { - archivesCh := make(chan []table.ModMailArchive) - go table.GetModmailArchivesByUser(userId, guildId, archivesCh) - archives = <-archivesCh + archives, err = dbclient.Client.ModmailArchive.GetByMember(guildId, userId, pageLimit, after, before) } else { - archivesCh := make(chan []table.ModMailArchive) - go table.GetModmailArchivesByGuild(guildId, archivesCh) - archives = <-archivesCh + archives, err = dbclient.Client.ModmailArchive.GetByGuild(guildId, pageLimit, after, before) } - for i := start; i < end && i < len(archives); i++ { + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + for _, archive := range archives { wrapped = append(wrapped, wrappedModLog{ - Uuid: archives[i].Uuid, - GuildId: archives[i].Guild, - UserId: archives[i].User, + Uuid: archive.Uuid.String(), + GuildId: archive.GuildId, + UserId: archive.UserId, }) } diff --git a/app/http/endpoints/api/panelcreate.go b/app/http/endpoints/api/panelcreate.go index 08e8c31..465e9ae 100644 --- a/app/http/endpoints/api/panelcreate.go +++ b/app/http/endpoints/api/panelcreate.go @@ -1,12 +1,19 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" - "github.com/TicketsBot/GoPanel/messagequeue" + "github.com/TicketsBot/GoPanel/config" + dbclient "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" + "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/database" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/objects/channel" + "github.com/rxdn/gdl/objects/channel/embed" + "github.com/rxdn/gdl/objects/channel/message" + "github.com/rxdn/gdl/rest" + "github.com/rxdn/gdl/rest/request" + "strconv" "strings" ) @@ -25,12 +32,19 @@ func CreatePanel(ctx *gin.Context) { data.MessageId = 0 // Check panel quota - premium := make(chan bool) - go utils.IsPremiumGuild(guildId, premium) - if !<-premium { - panels := make(chan []table.Panel) - go table.GetPanelsByGuild(guildId, panels) - if len(<-panels) > 0 { + premiumChan := make(chan bool) + go utils.IsPremiumGuild(guildId, premiumChan) + isPremium := <-premiumChan + if !isPremium { + panels, err := dbclient.Client.Panel.GetByGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + } + + if len(panels) > 0 { ctx.AbortWithStatusJSON(402, gin.H{ "success": false, "error": "You have exceeded your panel quota. Purchase premium to unlock more panels.", @@ -39,63 +53,118 @@ func CreatePanel(ctx *gin.Context) { } } - if !data.verifyTitle() { + if !data.doValidations(ctx, guildId) { + return + } + + msgId, err := data.sendEmbed(isPremium) + if err != nil { + if err == request.ErrForbidden { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": "I do not have permission to send messages in the specified channel", + }) + } else { + // TODO: Most appropriate error? + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + } + + return + } + + // Add reaction + emoji, _ := data.getEmoji() // already validated + if err = rest.CreateReaction(config.Conf.Bot.Token, ratelimit.Ratelimiter, data.ChannelId, msgId, emoji); err != nil { + if err == request.ErrForbidden { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": "I do not have permission to add reactions in the specified channel", + }) + } else { + // TODO: Most appropriate error? + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + } + + return + } + + // Store in DB + panel := database.Panel{ + MessageId: msgId, + ChannelId: data.ChannelId, + GuildId: guildId, + Title: data.Title, + Content: data.Content, + Colour: int32(data.Colour), + TargetCategory: data.CategoryId, + ReactionEmote: emoji, + } + + if err = dbclient.Client.Panel.Create(panel); err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + ctx.JSON(200, gin.H{ + "success": true, + "message_id": strconv.FormatUint(msgId, 10), + }) +} + +func (p *panel) doValidations(ctx *gin.Context, guildId uint64) bool { + if !p.verifyTitle() { ctx.AbortWithStatusJSON(400, gin.H{ "success": false, "error": "Panel titles must be between 1 - 255 characters in length", }) - return + return false } - if !data.verifyContent() { + if !p.verifyContent() { ctx.AbortWithStatusJSON(400, gin.H{ "success": false, "error": "Panel content must be between 1 - 1024 characters in length", }) - return + return false } channels := cache.Instance.GetGuildChannels(guildId) - if !data.verifyChannel(channels) { + if !p.verifyChannel(channels) { ctx.AbortWithStatusJSON(400, gin.H{ "success": false, "error": "Invalid channel", }) - return + return false } - if !data.verifyCategory(channels) { + if !p.verifyCategory(channels) { ctx.AbortWithStatusJSON(400, gin.H{ "success": false, "error": "Invalid channel category", }) - return + return false } - emoji, validEmoji := data.getEmoji() + _, validEmoji := p.getEmoji() if !validEmoji { ctx.AbortWithStatusJSON(400, gin.H{ "success": false, "error": "Invalid emoji. Simply use the emoji's name from Discord.", }) - return + return false } - // TODO: Move panel create logic here - go messagequeue.Client.PublishPanelCreate(table.Panel{ - ChannelId: data.ChannelId, - GuildId: guildId, - Title: data.Title, - Content: data.Content, - Colour: data.Colour, - TargetCategory: data.CategoryId, - ReactionEmote: emoji, - }) - - ctx.JSON(200, gin.H{ - "success": true, - }) + return true } func (p *panel) verifyTitle() bool { @@ -136,3 +205,24 @@ func (p *panel) verifyCategory(channels []channel.Channel) bool { return valid } + +func (p *panel) sendEmbed(isPremium bool) (messageId uint64, err error) { + e := embed.NewEmbed(). + SetTitle(p.Title). + SetDescription(p.Content). + SetColor(int(p.Colour)) + + if !isPremium { + // TODO: Don't harcode + e.SetFooter("Powered by ticketsbot.net", "https://cdn.discordapp.com/avatars/508391840525975553/ac2647ffd4025009e2aa852f719a8027.png?size=256") + } + + var msg message.Message + msg, err = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, p.ChannelId, rest.CreateMessageData{Embed: e}) + if err != nil { + return + } + + messageId = msg.Id + return +} diff --git a/app/http/endpoints/api/paneldelete.go b/app/http/endpoints/api/paneldelete.go index 1276d3e..11ae81a 100644 --- a/app/http/endpoints/api/paneldelete.go +++ b/app/http/endpoints/api/paneldelete.go @@ -2,7 +2,7 @@ package api import ( "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" @@ -21,11 +21,16 @@ func DeletePanel(ctx *gin.Context) { return } - // verify panel belongs to guild - panelChan := make(chan table.Panel) - go table.GetPanel(messageId, panelChan) - panel := <-panelChan + panel, err := database.Client.Panel.Get(messageId) + if err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + // verify panel belongs to guild if panel.GuildId != guildId { ctx.AbortWithStatusJSON(403, gin.H{ "success": false, @@ -34,8 +39,21 @@ func DeletePanel(ctx *gin.Context) { return } - go table.DeletePanel(messageId) - go rest.DeleteMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, panel.ChannelId, panel.MessageId) + if err := database.Client.Panel.Delete(messageId); err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + if err := rest.DeleteMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, panel.ChannelId, panel.MessageId); err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } ctx.JSON(200, gin.H{ "success": true, diff --git a/app/http/endpoints/api/panellist.go b/app/http/endpoints/api/panellist.go index 2b30f76..e3cd50f 100644 --- a/app/http/endpoints/api/panellist.go +++ b/app/http/endpoints/api/panellist.go @@ -1,7 +1,7 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/gin-gonic/gin" ) @@ -18,9 +18,14 @@ type panel struct { func ListPanels(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - panelsChan := make(chan []table.Panel) - go table.GetPanelsByGuild(guildId, panelsChan) - panels := <-panelsChan + panels, err := database.Client.Panel.GetByGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } wrapped := make([]panel, len(panels)) @@ -30,7 +35,7 @@ func ListPanels(ctx *gin.Context) { MessageId: p.MessageId, Title: p.Title, Content: p.Content, - Colour: p.Colour, + Colour: uint32(p.Colour), CategoryId: p.TargetCategory, Emote: p.ReactionEmote, } diff --git a/app/http/endpoints/api/sendmessage.go b/app/http/endpoints/api/sendmessage.go index 64ecdaa..1d3ced8 100644 --- a/app/http/endpoints/api/sendmessage.go +++ b/app/http/endpoints/api/sendmessage.go @@ -1,18 +1,16 @@ package api import ( - "bytes" - "encoding/json" "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" - "net/http" - "time" + "github.com/rxdn/gdl/rest/request" + "strconv" ) type sendMessageBody struct { @@ -23,6 +21,16 @@ func SendMessage(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) userId := ctx.Keys["userid"].(uint64) + // Get ticket ID + ticketId, err := strconv.Atoi(ctx.Param("ticketId")) + if err != nil { + ctx.AbortWithStatusJSON(400, gin.H{ + "success": false, + "error": "Invalid ticket ID", + }) + return + } + var body sendMessageBody if err := ctx.BindJSON(&body); err != nil { ctx.AbortWithStatusJSON(400, gin.H{ @@ -44,12 +52,10 @@ func SendMessage(ctx *gin.Context) { } // Get ticket - ticketChan := make(chan table.Ticket) - go table.GetTicket(ctx.Param("uuid"), ticketChan) - ticket := <-ticketChan + ticket, err := database.Client.Tickets.Get(ticketId, guildId) // Verify the ticket exists - if ticket.TicketId == 0 { + if ticket.UserId == 0 { ctx.AbortWithStatusJSON(404, gin.H{ "success": false, "error": "Ticket not found", @@ -58,7 +64,7 @@ func SendMessage(ctx *gin.Context) { } // Verify the user has permission to send to this guild - if ticket.Guild != guildId { + if ticket.GuildId != guildId { ctx.AbortWithStatusJSON(403, gin.H{ "success": false, "error": "Guild ID doesn't match", @@ -73,60 +79,61 @@ func SendMessage(ctx *gin.Context) { } // Preferably send via a webhook - webhookChan := make(chan *string) - go table.GetWebhookByUuid(ticket.Uuid, webhookChan) - webhook := <-webhookChan - - success := false - if webhook != nil { - // TODO: Use gdl execute webhook wrapper - success = executeWebhook(ticket.Uuid, *webhook, body.Message, user.Username, user.AvatarUrl(256)) + webhook, err := database.Client.Webhooks.Get(guildId, ticketId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return } - if !success { - body.Message = fmt.Sprintf("**%s**: %s", user.Username, body.Message) - if len(body.Message) > 2000 { - body.Message = body.Message[0:1999] - } + if webhook.Id != 0 { + // TODO: Use gdl execute webhook wrapper + _, err = rest.ExecuteWebhook(webhook.Token, ratelimit.Ratelimiter, webhook.Id, true, rest.WebhookBody{ + Content: body.Message, + Username: user.Username, + AvatarUrl: user.AvatarUrl(256), + }) - _, _ = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.Channel, rest.CreateMessageData{Content: body.Message}) + if err != nil { + fmt.Println(err.Error()) + // We can delete the webhook in this case + if err == request.ErrNotFound || err == request.ErrForbidden { + go database.Client.Webhooks.Delete(guildId, ticketId) + } + } else { + ctx.JSON(200, gin.H{ + "success": true, + }) + return + } + } + + fmt.Println(1) + + body.Message = fmt.Sprintf("**%s**: %s", user.Username, body.Message) + if len(body.Message) > 2000 { + body.Message = body.Message[0:1999] + } + + if ticket.ChannelId == nil { + ctx.AbortWithStatusJSON(404, gin.H{ + "success": false, + "error": "Ticket channel ID is nil", + }) + return + } + + if _, err = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, *ticket.ChannelId, rest.CreateMessageData{Content: body.Message}); err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return } ctx.JSON(200, gin.H{ "success": true, }) } - -func executeWebhook(uuid, webhook, content, username, avatar string) bool { - body := map[string]interface{}{ - "content": content, - "username": username, - "avatar_url": avatar, - } - encoded, err := json.Marshal(&body) - if err != nil { - return false - } - req, err := http.NewRequest("POST", fmt.Sprintf("https://canary.discordapp.com/api/webhooks/%s", webhook), bytes.NewBuffer(encoded)) - if err != nil { - return false - } - - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - client.Timeout = 3 * time.Second - - res, err := client.Do(req) - if err != nil { - return false - } - - if res.StatusCode == 404 || res.StatusCode == 403 { - go table.DeleteWebhookByUuid(uuid) - } else { - return true - } - - return false -} diff --git a/app/http/endpoints/api/settings.go b/app/http/endpoints/api/settings.go index 5a0a4e3..8c4279a 100644 --- a/app/http/endpoints/api/settings.go +++ b/app/http/endpoints/api/settings.go @@ -1,56 +1,99 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "context" + dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/database" "github.com/gin-gonic/gin" + "golang.org/x/sync/errgroup" ) type Settings struct { - Prefix string `json:"prefix"` - WelcomeMessaage string `json:"welcome_message"` - TicketLimit int `json:"ticket_limit"` - Category uint64 `json:"category,string"` - ArchiveChannel uint64 `json:"archive_channel,string"` - NamingScheme table.NamingScheme `json:"naming_scheme"` - PingEveryone bool `json:"ping_everyone"` - UsersCanClose bool `json:"users_can_close"` + Prefix string `json:"prefix"` + WelcomeMessaage string `json:"welcome_message"` + TicketLimit uint8 `json:"ticket_limit"` + Category uint64 `json:"category,string"` + ArchiveChannel uint64 `json:"archive_channel,string"` + NamingScheme database.NamingScheme `json:"naming_scheme"` + PingEveryone bool `json:"ping_everyone"` + UsersCanClose bool `json:"users_can_close"` } func GetSettingsHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - prefix := make(chan string) - go table.GetPrefix(guildId, prefix) + var prefix, welcomeMessage string + var ticketLimit uint8 + var category, archiveChannel uint64 + var allowUsersToClose, pingEveryone bool + var namingScheme database.NamingScheme - welcomeMessage := make(chan string) - go table.GetWelcomeMessage(guildId, welcomeMessage) + group, _ := errgroup.WithContext(context.Background()) - ticketLimit := make(chan int) - go table.GetTicketLimit(guildId, ticketLimit) + // prefix + group.Go(func() (err error) { + prefix, err = dbclient.Client.Prefix.Get(guildId) + return + }) - category := make(chan uint64) - go table.GetChannelCategory(guildId, category) + // welcome message + group.Go(func() (err error) { + welcomeMessage, err = dbclient.Client.WelcomeMessages.Get(guildId) + return + }) - archiveChannel := make(chan uint64) - go table.GetArchiveChannel(guildId, archiveChannel) + // ticket limit + group.Go(func() (err error) { + ticketLimit, err = dbclient.Client.TicketLimit.Get(guildId) + return + }) - allowUsersToClose := make(chan bool) - go table.IsUserCanClose(guildId, allowUsersToClose) + // category + group.Go(func() (err error) { + category, err = dbclient.Client.ChannelCategory.Get(guildId) + return + }) - namingScheme := make(chan table.NamingScheme) - go table.GetTicketNamingScheme(guildId, namingScheme) + // archive channel + group.Go(func() (err error) { + archiveChannel, err = dbclient.Client.ArchiveChannel.Get(guildId) + return + }) - pingEveryone := make(chan bool) - go table.GetPingEveryone(guildId, pingEveryone) + // allow users to close + group.Go(func() (err error) { + allowUsersToClose, err = dbclient.Client.UsersCanClose.Get(guildId) + return + }) + + // ping everyone + group.Go(func() (err error) { + pingEveryone, err = dbclient.Client.PingEveryone.Get(guildId) + return + }) + + // naming scheme + group.Go(func() (err error) { + namingScheme, err = dbclient.Client.NamingScheme.Get(guildId) + return + }) + + if err := group.Wait(); err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } ctx.JSON(200, Settings{ - Prefix: <-prefix, - WelcomeMessaage: <-welcomeMessage, - TicketLimit: <-ticketLimit, - Category: <-category, - ArchiveChannel: <-archiveChannel, - NamingScheme: <-namingScheme, - PingEveryone: <-pingEveryone, - UsersCanClose: <-allowUsersToClose, + Prefix: prefix, + WelcomeMessaage: welcomeMessage, + TicketLimit: ticketLimit, + Category: category, + ArchiveChannel: archiveChannel, + NamingScheme: namingScheme, + PingEveryone: pingEveryone, + UsersCanClose: allowUsersToClose, }) } diff --git a/app/http/endpoints/api/tagcreate.go b/app/http/endpoints/api/tagcreate.go index a716653..8dc0a84 100644 --- a/app/http/endpoints/api/tagcreate.go +++ b/app/http/endpoints/api/tagcreate.go @@ -1,7 +1,7 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/gin-gonic/gin" ) @@ -38,7 +38,7 @@ func CreateTag(ctx *gin.Context) { return } - if err := table.AddTag(guildId, data.Id, data.Content); err != nil { + if err := database.Client.Tag.Set(guildId, data.Id, data.Content); err != nil { ctx.AbortWithStatusJSON(500, gin.H{ "success": false, "error": err.Error(), diff --git a/app/http/endpoints/api/tagdelete.go b/app/http/endpoints/api/tagdelete.go index cb480a8..afe2b43 100644 --- a/app/http/endpoints/api/tagdelete.go +++ b/app/http/endpoints/api/tagdelete.go @@ -1,7 +1,7 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/gin-gonic/gin" ) @@ -17,7 +17,7 @@ func DeleteTag(ctx *gin.Context) { return } - if err := table.DeleteTag(guildId, tagId); err != nil { + if err := database.Client.Tag.Delete(guildId, tagId); err != nil { ctx.JSON(500, gin.H{ "success": false, "error": err.Error(), diff --git a/app/http/endpoints/api/tagslist.go b/app/http/endpoints/api/tagslist.go index ea30876..fd13e41 100644 --- a/app/http/endpoints/api/tagslist.go +++ b/app/http/endpoints/api/tagslist.go @@ -1,23 +1,22 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/gin-gonic/gin" ) +// TODO: Make client take new structure func TagsListHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - wrapped := make([]tag, 0) - - tags := make(chan []table.Tag) - go table.GetTags(guildId, tags) - for _, t := range <-tags { - wrapped = append(wrapped, tag{ - Id: t.Id, - Content: t.Content, + tags, err := database.Client.Tag.GetByGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), }) + return } - ctx.JSON(200, wrapped) + ctx.JSON(200, tags) } diff --git a/app/http/endpoints/api/updatesettings.go b/app/http/endpoints/api/updatesettings.go index 34089a6..af135af 100644 --- a/app/http/endpoints/api/updatesettings.go +++ b/app/http/endpoints/api/updatesettings.go @@ -1,7 +1,8 @@ package api import ( - "github.com/TicketsBot/GoPanel/database/table" + dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/objects/channel" @@ -42,12 +43,13 @@ func UpdateSettingsHandler(ctx *gin.Context) { }) } +// TODO: Return error func (s *Settings) updatePrefix(guildId uint64) bool { if s.Prefix == "" || len(s.Prefix) > 8 { return false } - go table.UpdatePrefix(guildId, s.Prefix) + go dbclient.Client.Prefix.Set(guildId, s.Prefix) return true } @@ -56,7 +58,7 @@ func (s *Settings) updateWelcomeMessage(guildId uint64) bool { return false } - go table.UpdateWelcomeMessage(guildId, s.WelcomeMessaage) + go dbclient.Client.WelcomeMessages.Set(guildId, s.WelcomeMessaage) return true } @@ -65,7 +67,7 @@ func (s *Settings) updateTicketLimit(guildId uint64) bool { return false } - go table.UpdateTicketLimit(guildId, s.TicketLimit) + go dbclient.Client.TicketLimit.Set(guildId, s.TicketLimit) return true } @@ -82,7 +84,7 @@ func (s *Settings) updateCategory(channels []channel.Channel, guildId uint64) bo return false } - go table.UpdateChannelCategory(guildId, s.Category) + go dbclient.Client.ChannelCategory.Set(guildId, s.Category) return true } @@ -99,11 +101,11 @@ func (s *Settings) updateArchiveChannel(channels []channel.Channel, guildId uint return false } - go table.UpdateArchiveChannel(guildId, s.ArchiveChannel) + go dbclient.Client.ArchiveChannel.Set(guildId, s.ArchiveChannel) return true } -var validScheme = []table.NamingScheme{table.Id, table.Username} +var validScheme = []database.NamingScheme{database.Id, database.Username} func (s *Settings) updateNamingScheme(guildId uint64) bool { var valid bool for _, scheme := range validScheme { @@ -117,14 +119,14 @@ func (s *Settings) updateNamingScheme(guildId uint64) bool { return false } - go table.SetTicketNamingScheme(guildId, s.NamingScheme) + go dbclient.Client.NamingScheme.Set(guildId, s.NamingScheme) return true } func (s *Settings) updatePingEveryone(guildId uint64) { - go table.UpdatePingEveryone(guildId, s.PingEveryone) + go dbclient.Client.PingEveryone.Set(guildId, s.PingEveryone) } func (s *Settings) updateUsersCanClose(guildId uint64) { - go table.SetUserCanClose(guildId, s.UsersCanClose) + go dbclient.Client.UsersCanClose.Set(guildId, s.UsersCanClose) } diff --git a/app/http/endpoints/manage/logsview.go b/app/http/endpoints/manage/logsview.go index 56eb7be..f9e3f3b 100644 --- a/app/http/endpoints/manage/logsview.go +++ b/app/http/endpoints/manage/logsview.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/archiverclient" @@ -41,20 +41,27 @@ func LogViewHandler(ctx *gin.Context) { } // get ticket object - ticketChan := make(chan table.Ticket) - go table.GetTicketById(guildId, ticketId, ticketChan) - ticket := <-ticketChan + ticket, err := database.Client.Tickets.Get(ticketId, guildId) + if err != nil { + // TODO: 500 error page + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } // Verify this is a valid ticket and it is closed - if ticket.Uuid == "" || ticket.IsOpen { + if ticket.UserId == 0 || ticket.Open { ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs", guild.Id)) return } // Verify the user has permissions to be here + // TODO: Allow support reps to view isAdmin := make(chan bool) go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin && ticket.Owner != userId { + if !<-isAdmin && ticket.UserId != userId { ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page return } diff --git a/app/http/endpoints/manage/modmaillogsview.go b/app/http/endpoints/manage/modmaillogsview.go index f0906fd..1783401 100644 --- a/app/http/endpoints/manage/modmaillogsview.go +++ b/app/http/endpoints/manage/modmaillogsview.go @@ -4,12 +4,13 @@ import ( "errors" "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/archiverclient" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" + "github.com/gofrs/uuid" "strconv" ) @@ -33,21 +34,35 @@ func ModmailLogViewHandler(ctx *gin.Context) { guild, _ := cache.Instance.GetGuild(guildId, false) // get ticket UUID - uuid := ctx.Param("uuid") + archiveUuid, err := uuid.FromString(ctx.Param("uuid")) + if err != nil { + // TODO: 404 error page + ctx.AbortWithStatusJSON(404, gin.H{ + "success": false, + "error": "Modmail archive not found", + }) + return + } // get ticket object - archiveCh := make(chan table.ModMailArchive) - go table.GetModmailArchive(uuid, archiveCh) - archive := <-archiveCh + archive, err := database.Client.ModmailArchive.Get(archiveUuid) + if err != nil { + // TODO: 500 error page + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } // Verify this is a valid ticket and it is closed - if archive.Uuid == "" { + if archive.Uuid == uuid.Nil{ ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id)) return } // Verify this modmail ticket was for this guild - if archive.Guild != guildId { + if archive.GuildId != guildId { ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id)) return } @@ -55,13 +70,13 @@ func ModmailLogViewHandler(ctx *gin.Context) { // Verify the user has permissions to be here isAdmin := make(chan bool) go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin && archive.User != userId { + if !<-isAdmin && archive.UserId != userId { ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page return } // retrieve ticket messages from bucket - messages, err := Archiver.GetModmail(guildId, uuid) + messages, err := Archiver.GetModmail(guildId, archiveUuid.String()) if err != nil { if errors.Is(err, archiverclient.ErrExpired) { ctx.String(200, "Archives expired: Purchase premium for permanent log storage") // TODO: Actual error page @@ -73,7 +88,7 @@ func ModmailLogViewHandler(ctx *gin.Context) { } // format to html - html, err := Archiver.Encode(messages, fmt.Sprintf("modmail-%s", uuid)) + html, err := Archiver.Encode(messages, fmt.Sprintf("modmail-%s", archiveUuid)) if err != nil { ctx.String(500, fmt.Sprintf("Failed to retrieve archive - please contact the developers: %s", err.Error())) return diff --git a/app/http/endpoints/manage/settings.go b/app/http/endpoints/manage/settings.go index 65b7f0d..cddfa58 100644 --- a/app/http/endpoints/manage/settings.go +++ b/app/http/endpoints/manage/settings.go @@ -1,85 +1,19 @@ package manage import ( - "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" - "github.com/TicketsBot/GoPanel/rpc/cache" - "github.com/TicketsBot/GoPanel/utils" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" - "github.com/rxdn/gdl/objects/channel" - "strconv" ) func SettingsHandler(ctx *gin.Context) { store := sessions.Default(ctx) - - userId := utils.GetUserId(store) - - // Verify the guild exists - guildIdStr := ctx.Param("id") - guildId, err := strconv.ParseUint(guildIdStr, 10, 64) - if err != nil { - ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 404 Page - return - } - - // Check the bot is in the guild - guild, isInGuild := cache.Instance.GetGuild(guildId, false) - if !isInGuild { - ctx.Redirect(302, fmt.Sprintf("https://invite.ticketsbot.net/?guild_id=%s&disable_guild_select=true&response_type=code&scope=bot%%20identify&redirect_uri=%s", guildIdStr, config.Conf.Server.BaseUrl)) - return - } - - // Verify the user has permissions to be here - isAdmin := make(chan bool) - go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin { - ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page - return - } - - namingSchemeChan := make(chan table.NamingScheme) - go table.GetTicketNamingScheme(guildId, namingSchemeChan) - namingScheme := <-namingSchemeChan - - // get guild channels from cache - channels := cache.Instance.GetGuildChannels(guildId) - - // separate out categories - categories := make([]channel.Channel, 0) - for _, ch := range channels { - if ch.Type == channel.ChannelTypeGuildCategory { - categories = append(categories, ch) - } - } - - panelSettings := table.GetPanelSettings(guildId) - - // Users can close - usersCanCloseChan := make(chan bool) - go table.IsUserCanClose(guildId, usersCanCloseChan) - usersCanClose := <-usersCanCloseChan - - invalidPrefix := ctx.Query("validPrefix") == "false" - invalidWelcomeMessage := ctx.Query("validWelcomeMessage") == "false" - invalidTicketLimit := ctx.Query("validTicketLimit") == "false" + guildId := ctx.Keys["guildid"].(uint64) ctx.HTML(200, "manage/settings", gin.H{ - "name": store.Get("name").(string), - "guildId": guildIdStr, - "avatar": store.Get("avatar").(string), - "categories": categories, - "channels": channels, - "invalidPrefix": invalidPrefix, - "invalidWelcomeMessage": invalidWelcomeMessage, - "invalidTicketLimit": invalidTicketLimit, - "csrf": store.Get("csrf").(string), - "paneltitle": panelSettings.Title, - "panelcontent": panelSettings.Content, - "panelcolour": strconv.FormatInt(int64(panelSettings.Colour), 16), - "usersCanClose": usersCanClose, - "namingScheme": string(namingScheme), + "name": store.Get("name").(string), + "guildId": guildId, + "avatar": store.Get("avatar").(string), + "baseUrl": config.Conf.Server.BaseUrl, }) } diff --git a/app/http/endpoints/manage/ticketview.go b/app/http/endpoints/manage/ticketview.go index e9417eb..61fe34d 100644 --- a/app/http/endpoints/manage/ticketview.go +++ b/app/http/endpoints/manage/ticketview.go @@ -11,10 +11,10 @@ func TicketViewHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) ctx.HTML(200, "manage/ticketview", gin.H{ - "name": store.Get("name").(string), - "guildId": guildId, - "avatar": store.Get("avatar").(string), - "baseUrl": config.Conf.Server.BaseUrl, - "uuid": ctx.Param("uuid"), + "name": store.Get("name").(string), + "guildId": guildId, + "avatar": store.Get("avatar").(string), + "baseUrl": config.Conf.Server.BaseUrl, + "ticketId": ctx.Param("ticketId"), }) } diff --git a/app/http/endpoints/root/callback.go b/app/http/endpoints/root/callback.go index 0faa5ca..452e054 100644 --- a/app/http/endpoints/root/callback.go +++ b/app/http/endpoints/root/callback.go @@ -1,14 +1,13 @@ package root import ( - "encoding/base64" - "encoding/json" "fmt" "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + dbclient "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/GoPanel/utils/discord" userEndpoint "github.com/TicketsBot/GoPanel/utils/discord/endpoints/user" + "github.com/TicketsBot/database" "github.com/apex/log" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" @@ -92,6 +91,8 @@ func CallbackHandler(ctx *gin.Context) { return } + var wrappedGuilds []database.UserGuild + // endpoint's partial guild doesn't include ownerid // we only user cached guilds on the index page, so it doesn't matter if we don't have have the real owner id // if the user isn't the owner, as we pull from the cache on other endpoints @@ -99,16 +100,17 @@ func CallbackHandler(ctx *gin.Context) { if guild.Owner { guild.OwnerId = currentUser.Id } + + wrappedGuilds = append(wrappedGuilds, database.UserGuild{ + GuildId: guild.Id, + Name: guild.Name, + Owner: guild.Owner, + UserPermissions: int32(guild.Permissions), + }) } - marshalled, err := json.Marshal(guilds) - if err != nil { - log.Error(err.Error()) - return - } - - // TODO: unfuck this - table.UpdateGuilds(currentUser.Id, base64.StdEncoding.EncodeToString(marshalled)) + // TODO: Error handling + go dbclient.Client.UserGuilds.Set(currentUser.Id, wrappedGuilds) }() } diff --git a/app/http/endpoints/root/index.go b/app/http/endpoints/root/index.go index f2a4308..9723c23 100644 --- a/app/http/endpoints/root/index.go +++ b/app/http/endpoints/root/index.go @@ -2,7 +2,7 @@ package root import ( "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/utils" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" @@ -13,19 +13,31 @@ func IndexHandler(ctx *gin.Context) { store := sessions.Default(ctx) userId := utils.GetUserId(store) - userGuilds := table.GetGuilds(userId) + userGuilds, err := database.Client.UserGuilds.Get(userId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + adminGuilds := make([]guild.Guild, 0) for _, g := range userGuilds { fakeGuild := guild.Guild{ - Id: g.Id, - OwnerId: g.OwnerId, - Permissions: g.Permissions, + Id: g.GuildId, + Owner: g.Owner, + Permissions: int(g.UserPermissions), + } + + if g.Owner { + fakeGuild.OwnerId = userId } isAdmin := make(chan bool) go utils.IsAdmin(fakeGuild, userId, isAdmin) if <-isAdmin { - adminGuilds = append(adminGuilds, g) + adminGuilds = append(adminGuilds, fakeGuild) } } diff --git a/app/http/middleware/authenticatetoken.go b/app/http/middleware/authenticatetoken.go index 4bab341..8c12ef7 100644 --- a/app/http/middleware/authenticatetoken.go +++ b/app/http/middleware/authenticatetoken.go @@ -1,7 +1,6 @@ package middleware import ( - "errors" "fmt" "github.com/TicketsBot/GoPanel/config" "github.com/dgrijalva/jwt-go" @@ -22,6 +21,7 @@ func AuthenticateToken(ctx *gin.Context) { if err != nil { ctx.AbortWithStatusJSON(403, gin.H{ + "success": false, "error": err.Error(), }) return @@ -31,7 +31,8 @@ func AuthenticateToken(ctx *gin.Context) { userId, hasUserId := claims["userid"] if !hasUserId { ctx.AbortWithStatusJSON(403, gin.H{ - "error": errors.New("token is invalid"), + "success": false, + "error": "Token is invalid", }) return } @@ -39,7 +40,8 @@ func AuthenticateToken(ctx *gin.Context) { parsedId, err := strconv.ParseUint(userId.(string), 10, 64) if err != nil { ctx.AbortWithStatusJSON(403, gin.H{ - "error": errors.New("token is invalid"), + "success": false, + "error": "Token is invalid", }) return } @@ -47,7 +49,8 @@ func AuthenticateToken(ctx *gin.Context) { ctx.Keys["userid"] = parsedId } else { ctx.AbortWithStatusJSON(403, gin.H{ - "error": errors.New("token is invalid"), + "success": false, + "error": "Token is invalid", }) return } diff --git a/app/http/server.go b/app/http/server.go index 6cce309..3baea41 100644 --- a/app/http/server.go +++ b/app/http/server.go @@ -66,8 +66,7 @@ func StartServer() { authenticateGuild.GET("/manage/:id/tags", manage.TagsHandler) authenticateGuild.GET("/manage/:id/tickets", manage.TicketListHandler) - authenticateGuild.GET("/manage/:id/tickets/view/:uuid", manage.TicketViewHandler) - authenticateGuild.POST("/manage/:id/tickets/view/:uuid", api.SendMessage) + authenticateGuild.GET("/manage/:id/tickets/view/:ticketId", manage.TicketViewHandler) authorized.GET("/webchat", manage.WebChatWs) } @@ -90,13 +89,13 @@ func StartServer() { guildAuthApi.PUT("/:id/panels", api.CreatePanel) guildAuthApi.DELETE("/:id/panels/:message", api.DeletePanel) - guildAuthApi.GET("/:id/logs/:page", api.GetLogs) - guildAuthApi.GET("/:id/modmail/logs/:page", api.GetModmailLogs) + guildAuthApi.GET("/:id/logs/", api.GetLogs) + guildAuthApi.GET("/:id/modmail/logs/", api.GetModmailLogs) guildAuthApi.GET("/:id/tickets", api.GetTickets) - guildAuthApi.GET("/:id/tickets/:uuid", api.GetTicket) - guildAuthApi.POST("/:id/tickets/:uuid", api.SendMessage) - guildAuthApi.DELETE("/:id/tickets/:uuid", api.CloseTicket) + guildAuthApi.GET("/:id/tickets/:ticketId", api.GetTicket) + guildAuthApi.POST("/:id/tickets/:ticketId", api.SendMessage) + guildAuthApi.DELETE("/:id/tickets/:ticketId", api.CloseTicket) guildAuthApi.GET("/:id/tags", api.TagsListHandler) guildAuthApi.PUT("/:id/tags", api.CreateTag) diff --git a/config.toml.example b/config.toml.example index 1e273bc..fb83577 100644 --- a/config.toml.example +++ b/config.toml.example @@ -16,12 +16,8 @@ id= secret="" redirectUri="" -[mariadb] -host="127.0.0.1" -username="ryan" -password="ryan" -database="tickets" -threads=5 +[database] +uri="postgres://user:pwd@localhost:5432/database?pool_max_conns=10" [bot] token="" diff --git a/config/config.go b/config/config.go index 4c713d5..38d935e 100644 --- a/config/config.go +++ b/config/config.go @@ -7,13 +7,13 @@ import ( type ( Config struct { - Admins []string - Server Server - Oauth Oauth - MariaDB MariaDB - Bot Bot - Redis Redis - Cache Cache + Admins []string + Server Server + Oauth Oauth + Database Database + Bot Bot + Redis Redis + Cache Cache } Server struct { @@ -41,12 +41,8 @@ type ( RedirectUri string } - MariaDB struct { - Host string - Username string - Password string - Database string - Threads int + Database struct { + Uri string } Bot struct { diff --git a/database/database.go b/database/database.go index f13c70e..b4bb7fc 100644 --- a/database/database.go +++ b/database/database.go @@ -1,35 +1,31 @@ -package database - -import ( - "fmt" - "github.com/TicketsBot/GoPanel/config" - _ "github.com/go-sql-driver/mysql" - "github.com/jinzhu/gorm" -) - -var ( - Database gorm.DB -) - -func ConnectToDatabase() { - uri := fmt.Sprintf( - "%s:%s@tcp(%s:3306)/%s?charset=utf8mb4&parseTime=True&loc=Local", - config.Conf.MariaDB.Username, - config.Conf.MariaDB.Password, - config.Conf.MariaDB.Host, - config.Conf.MariaDB.Database, - ) - - db, err := gorm.Open("mysql", uri) - if err != nil { - panic(err) - } - - db.DB().SetMaxOpenConns(config.Conf.MariaDB.Threads) - db.DB().SetMaxIdleConns(0) - - db.Set("gorm:table_options", "charset=utf8mb4") - db.BlockGlobalUpdate(true) - - Database = *db -} +package database + +import ( + "context" + "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/database" + "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v4/log/logrusadapter" + "github.com/jackc/pgx/v4/pgxpool" + "github.com/sirupsen/logrus" +) + +var Client *database.Database + +func ConnectToDatabase() { + config, err := pgxpool.ParseConfig(config.Conf.Database.Uri); if err != nil { + panic(err) + } + + // TODO: Sentry + config.ConnConfig.LogLevel = pgx.LogLevelWarn + config.ConnConfig.Logger = logrusadapter.NewLogger(logrus.New()) + + pool, err := pgxpool.ConnectConfig(context.Background(), config) + if err != nil { + panic(err) + } + + Client = database.NewDatabase(pool) + Client.CreateTables(pool) +} diff --git a/database/table/archivechannel.go b/database/table/archivechannel.go deleted file mode 100644 index 8bbc01b..0000000 --- a/database/table/archivechannel.go +++ /dev/null @@ -1,25 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type ArchiveChannel struct { - Guild uint64 `gorm:"column:GUILDID"` - Channel uint64 `gorm:"column:CHANNELID"` -} - -func (ArchiveChannel) TableName() string { - return "archivechannel" -} - -func UpdateArchiveChannel(guildId uint64, channelId uint64) { - var channel ArchiveChannel - database.Database.Where(ArchiveChannel{Guild: guildId}).Assign(ArchiveChannel{Channel: channelId}).FirstOrCreate(&channel) -} - -func GetArchiveChannel(guildId uint64, ch chan uint64) { - var channel ArchiveChannel - database.Database.Where(&ArchiveChannel{Guild: guildId}).First(&channel) - ch <- channel.Channel -} diff --git a/database/table/blacklist.go b/database/table/blacklist.go deleted file mode 100644 index 6c36166..0000000 --- a/database/table/blacklist.go +++ /dev/null @@ -1,35 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type BlacklistNode struct { - Assoc int `gorm:"column:ASSOCID;type:int;primary_key;auto_increment"` - Guild uint64 `gorm:"column:GUILDID"` - User uint64 `gorm:"column:USERID"` -} - -func (BlacklistNode) TableName() string { - return "blacklist" -} - -func IsBlacklisted(guildId, userId uint64) bool { - var count int - database.Database.Table("blacklist").Where(&BlacklistNode{Guild: guildId, User: userId}).Count(&count) - return count > 0 -} - -func AddBlacklist(guildId, userId uint64) { - database.Database.Create(&BlacklistNode{Guild: guildId, User: userId}) -} - -func RemoveBlacklist(guildId, userId uint64) { - database.Database.Where(BlacklistNode{Guild: guildId, User: userId}).Delete(BlacklistNode{}) -} - -func GetBlacklistNodes(guildId uint64) []BlacklistNode { - var nodes []BlacklistNode - database.Database.Where(&BlacklistNode{Guild: guildId}).Find(&nodes) - return nodes -} diff --git a/database/table/channelcategory.go b/database/table/channelcategory.go deleted file mode 100644 index b1f905c..0000000 --- a/database/table/channelcategory.go +++ /dev/null @@ -1,24 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type ChannelCategory struct { - GuildId uint64 `gorm:"column:GUILDID"` - Category uint64 `gorm:"column:CATEGORYID"` -} - -func (ChannelCategory) TableName() string { - return "channelcategory" -} - -func UpdateChannelCategory(guildId uint64, categoryId uint64) { - database.Database.Where(&ChannelCategory{GuildId: guildId}).Assign(&ChannelCategory{Category: categoryId}).FirstOrCreate(&ChannelCategory{}) -} - -func GetChannelCategory(guildId uint64, ch chan uint64) { - var category ChannelCategory - database.Database.Where(&ChannelCategory{GuildId: guildId}).First(&category) - ch <- category.Category -} diff --git a/database/table/guilds.go b/database/table/guilds.go deleted file mode 100644 index 8819d99..0000000 --- a/database/table/guilds.go +++ /dev/null @@ -1,39 +0,0 @@ -package table - -import ( - "encoding/base64" - "encoding/json" - "github.com/TicketsBot/GoPanel/database" - "github.com/rxdn/gdl/objects/guild" -) - -type GuildCache struct { - UserId uint64 `gorm:"column:USERID"` - Guilds string `gorm:"column:guilds;type:mediumtext"` -} - -func (GuildCache) TableName() string { - return "guildscache" -} - -// this is horrible -func UpdateGuilds(userId uint64, guilds string) { - var cache GuildCache - database.Database.Where(&GuildCache{UserId: userId}).Assign(&GuildCache{Guilds: guilds}).FirstOrCreate(&cache) -} - -func GetGuilds(userId uint64) []guild.Guild { - var cache GuildCache - database.Database.Where(&GuildCache{UserId: userId}).First(&cache) - decoded, err := base64.StdEncoding.DecodeString(cache.Guilds) - if err != nil { - return nil - } - - var guilds []guild.Guild - if err := json.Unmarshal(decoded, &guilds); err != nil { - return nil - } - - return guilds -} diff --git a/database/table/modmailarchive.go b/database/table/modmailarchive.go deleted file mode 100644 index 949c534..0000000 --- a/database/table/modmailarchive.go +++ /dev/null @@ -1,39 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" - "time" -) - -type ModMailArchive struct { - Uuid string `gorm:"column:UUID;type:varchar(36);unique;primary_key"` - Guild uint64 `gorm:"column:GUILDID"` - User uint64 `gorm:"column:USERID"` - CloseTime time.Time `gorm:"column:CLOSETIME"` -} - -func (ModMailArchive) TableName() string { - return "modmail_archive" -} - -func (m *ModMailArchive) Store() { - database.Database.Create(m) -} - -func GetModmailArchive(uuid string, ch chan ModMailArchive) { - var row ModMailArchive - database.Database.Where(ModMailArchive{Uuid: uuid}).Take(&row) - ch <- row -} - -func GetModmailArchivesByUser(userId, guildId uint64, ch chan []ModMailArchive) { - var rows []ModMailArchive - database.Database.Where(ModMailArchive{User: userId, Guild: guildId}).Order("CLOSETIME desc").Find(&rows) - ch <- rows -} - -func GetModmailArchivesByGuild(guildId uint64, ch chan []ModMailArchive) { - var rows []ModMailArchive - database.Database.Where(ModMailArchive{Guild: guildId}).Order("CLOSETIME desc").Find(&rows) - ch <- rows -} diff --git a/database/table/namingscheme.go b/database/table/namingscheme.go deleted file mode 100644 index abef04d..0000000 --- a/database/table/namingscheme.go +++ /dev/null @@ -1,37 +0,0 @@ -package table - -import "github.com/TicketsBot/GoPanel/database" - -type TicketNamingScheme struct { - Guild uint64 `gorm:"column:GUILDID;unique;primary_key"` - NamingScheme string `gorm:"column:NAMINGSCHEME;type:VARCHAR(16)"` -} - -type NamingScheme string - -const ( - Id NamingScheme = "id" - Username NamingScheme = "username" -) - -var Schemes = []NamingScheme{Id, Username} - -func (TicketNamingScheme) TableName() string { - return "TicketNamingScheme" -} - -func GetTicketNamingScheme(guild uint64, ch chan NamingScheme) { - var node TicketNamingScheme - database.Database.Where(TicketNamingScheme{Guild: guild}).First(&node) - namingScheme := node.NamingScheme - - if namingScheme == "" { - ch <- Id - } else { - ch <- NamingScheme(namingScheme) - } -} - -func SetTicketNamingScheme(guild uint64, scheme NamingScheme) { - database.Database.Where(&TicketNamingScheme{Guild: guild}).Assign(&TicketNamingScheme{NamingScheme: string(scheme)}).FirstOrCreate(&TicketNamingScheme{}) -} diff --git a/database/table/panels.go b/database/table/panels.go deleted file mode 100644 index 59ed716..0000000 --- a/database/table/panels.go +++ /dev/null @@ -1,56 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type Panel struct { - MessageId uint64 `gorm:"column:MESSAGEID"` - ChannelId uint64 `gorm:"column:CHANNELID"` - GuildId uint64 `gorm:"column:GUILDID"` // Might be useful in the future so we store it - Title string `gorm:"column:TITLE;type:VARCHAR(255)"` - Content string `gorm:"column:CONTENT;type:TEXT"` - Colour uint32 `gorm:"column:COLOUR` - TargetCategory uint64 `gorm:"column:TARGETCATEGORY"` - ReactionEmote string `gorm:"column:REACTIONEMOTE;type:VARCHAR(32)"` -} - -func (Panel) TableName() string { - return "panels" -} - -func AddPanel(messageId, channelId, guildId uint64, title, content string, colour uint32, targetCategory uint64, reactionEmote string) { - database.Database.Create(&Panel{ - MessageId: messageId, - ChannelId: channelId, - GuildId: guildId, - - Title: title, - Content: content, - Colour: colour, - TargetCategory: targetCategory, - ReactionEmote: reactionEmote, - }) -} - -func IsPanel(messageId uint64, ch chan bool) { - var count int - database.Database.Table(Panel{}.TableName()).Where(Panel{MessageId: messageId}).Count(&count) - ch <- count > 0 -} - -func GetPanelsByGuild(guildId uint64, ch chan []Panel) { - var panels []Panel - database.Database.Where(Panel{GuildId: guildId}).Find(&panels) - ch <- panels -} - -func GetPanel(messageId uint64, ch chan Panel) { - var row Panel - database.Database.Where(Panel{MessageId: messageId}).Take(&row) - ch <- row -} - -func DeletePanel(msgId uint64) { - database.Database.Where(Panel{MessageId: msgId}).Delete(Panel{}) -} diff --git a/database/table/panelsettings.go b/database/table/panelsettings.go deleted file mode 100644 index f53fdc0..0000000 --- a/database/table/panelsettings.go +++ /dev/null @@ -1,61 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type PanelSettings struct { - GuildId uint64 `gorm:"column:GUILDID"` - Title string `gorm:"column:TITLE;type:VARCHAR(255)"` - Content string `gorm:"column:CONTENT;type:TEXT"` - Colour int `gorm:"column:COLOUR` -} - -func (PanelSettings) TableName() string { - return "panelsettings" -} - -func UpdatePanelSettings(guildId uint64, title string, content string, colour int) { - settings := PanelSettings{ - Title: title, - Content: content, - Colour: colour, - } - - database.Database.Where(&PanelSettings{GuildId: guildId}).Assign(&settings).FirstOrCreate(&PanelSettings{}) -} - -func UpdatePanelTitle(guildId uint64, title string) { - settings := PanelSettings{ - Title: title, - } - - database.Database.Where(&PanelSettings{GuildId: guildId}).Assign(&settings).FirstOrCreate(&PanelSettings{}) -} - -func UpdatePanelContent(guildId uint64, content string) { - settings := PanelSettings{ - Content: content, - } - - database.Database.Where(&PanelSettings{GuildId: guildId}).Assign(&settings).FirstOrCreate(&PanelSettings{}) -} - -func UpdatePanelColour(guildId uint64, colour int) { - settings := PanelSettings{ - Colour: colour, - } - - database.Database.Where(&PanelSettings{GuildId: guildId}).Assign(&settings).FirstOrCreate(&PanelSettings{}) -} - -func GetPanelSettings(guildId uint64) PanelSettings { - settings := PanelSettings{ - Title: "Open A Ticket", - Content: "React with :envelope_with_arrow: to open a ticket", - Colour: 2335514, - } - database.Database.Where(PanelSettings{GuildId: guildId}).First(&settings) - - return settings -} diff --git a/database/table/permissions.go b/database/table/permissions.go deleted file mode 100644 index 535fd72..0000000 --- a/database/table/permissions.go +++ /dev/null @@ -1,44 +0,0 @@ -package table - -import "github.com/TicketsBot/GoPanel/database" - -type PermissionNode struct { - GuildId uint64 `gorm:"column:GUILDID"` - UserId uint64 `gorm:"column:USERID"` - IsSupport bool `gorm:"column:ISSUPPORT"` - IsAdmin bool `gorm:"column:ISADMIN"` -} - -func (PermissionNode) TableName() string { - return "permissions" -} - -func GetAdminGuilds(userId uint64) []uint64 { - var nodes []PermissionNode - database.Database.Where(&PermissionNode{UserId: userId}).Find(&nodes) - - ids := make([]uint64, 0) - for _, node := range nodes { - ids = append(ids, node.GuildId) - } - - return ids -} - -func IsSupport(guildId uint64, userId uint64) bool { - var node PermissionNode - database.Database.Where(&PermissionNode{GuildId: guildId, UserId: userId}).Take(&node) - return node.IsSupport -} - -func IsAdmin(guildId uint64, userId uint64) bool { - var node PermissionNode - database.Database.Where(&PermissionNode{GuildId: guildId, UserId: userId}).Take(&node) - return node.IsAdmin -} - -func IsStaff(guildId uint64, userId uint64) bool { - var node PermissionNode - database.Database.Where(&PermissionNode{GuildId: guildId, UserId: userId}).Take(&node) - return node.IsAdmin || node.IsSupport -} diff --git a/database/table/pingeveryone.go b/database/table/pingeveryone.go deleted file mode 100644 index b3c2003..0000000 --- a/database/table/pingeveryone.go +++ /dev/null @@ -1,36 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type PingEveryone struct { - GuildId uint64 `gorm:"column:GUILDID"` - PingEveryone bool `gorm:"column:PINGEVERYONE;type:TINYINT"` -} - -func (PingEveryone) TableName() string { - return "pingeveryone" -} - -// tldr I hate gorm -func UpdatePingEveryone(guildId uint64, pingEveryone bool) { - var settings []PingEveryone - database.Database.Where(&PingEveryone{GuildId: guildId}).Find(&settings) - - updated := PingEveryone{guildId, pingEveryone} - - if len(settings) == 0 { - database.Database.Create(&updated) - } else { - database.Database.Table("pingeveryone").Where("GUILDID = ?", guildId).Update("PINGEVERYONE", pingEveryone) - } - - //database.Database.Where(&PingEveryone{GuildId: guildId}).Assign(&updated).FirstOrCreate(&PingEveryone{}) -} - -func GetPingEveryone(guildId uint64, ch chan bool) { - pingEveryone := PingEveryone{PingEveryone: true} - database.Database.Where(&PingEveryone{GuildId: guildId}).First(&pingEveryone) - ch <- pingEveryone.PingEveryone -} diff --git a/database/table/prefix.go b/database/table/prefix.go deleted file mode 100644 index f0325d0..0000000 --- a/database/table/prefix.go +++ /dev/null @@ -1,24 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type Prefix struct { - GuildId uint64 `gorm:"column:GUILDID"` - Prefix string `gorm:"column:PREFIX;type:varchar(8)"` -} - -func (Prefix) TableName() string { - return "prefix" -} - -func UpdatePrefix(guildId uint64, prefix string) { - database.Database.Where(&Prefix{GuildId: guildId}).Assign(&Prefix{Prefix: prefix}).FirstOrCreate(&Prefix{}) -} - -func GetPrefix(guildId uint64, ch chan string) { - prefix := Prefix{Prefix: "t!"} - database.Database.Where(&Prefix{GuildId: guildId}).First(&prefix) - ch <- prefix.Prefix -} diff --git a/database/table/premiumguilds.go b/database/table/premiumguilds.go deleted file mode 100644 index a7b4d9f..0000000 --- a/database/table/premiumguilds.go +++ /dev/null @@ -1,72 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" - "strings" - "time" -) - -type PremiumGuilds struct { - Guild uint64 `gorm:"column:GUILDID;unique;primary_key"` - Expiry int64 `gorm:"column:EXPIRY"` - User uint64 `gorm:"column:USERID"` - ActivatedBy uint64 `gorm:"column:ACTIVATEDBY"` - Keys string `gorm:"column:KEYSUSED"` -} - -func (PremiumGuilds) TableName() string { - return "premiumguilds" -} - -func IsPremium(guild uint64, ch chan bool) { - var node PremiumGuilds - database.Database.Where(PremiumGuilds{Guild: guild}).First(&node) - - if node.Expiry == 0 { - ch <- false - return - } - - current := time.Now().UnixNano() / int64(time.Millisecond) - ch <- node.Expiry > current -} - -func AddPremium(key string, guild, userId uint64, length int64, activatedBy uint64) { - var expiry int64 - - hasPrem := make(chan bool) - go IsPremium(guild, hasPrem) - isPremium := <-hasPrem - - if isPremium { - expiryChan := make(chan int64) - go GetExpiry(guild, expiryChan) - currentExpiry := <-expiryChan - - expiry = currentExpiry + length - } else { - current := time.Now().UnixNano() / int64(time.Millisecond) - expiry = current + length - } - - keysChan := make(chan []string) - go GetKeysUsed(guild, keysChan) - keys := <-keysChan - keys = append(keys, key) - keysStr := strings.Join(keys, ",") - - var node PremiumGuilds - database.Database.Where(PremiumGuilds{Guild: guild}).Assign(PremiumGuilds{Expiry: expiry, User: userId, ActivatedBy: activatedBy, Keys: keysStr}).FirstOrCreate(&node) -} - -func GetExpiry(guild uint64, ch chan int64) { - var node PremiumGuilds - database.Database.Where(PremiumGuilds{Guild: guild}).First(&node) - ch <- node.Expiry -} - -func GetKeysUsed(guild uint64, ch chan []string) { - var node PremiumGuilds - database.Database.Where(PremiumGuilds{Guild: guild}).First(&node) - ch <- strings.Split(node.Keys, ",") -} diff --git a/database/table/rolepermissions.go b/database/table/rolepermissions.go deleted file mode 100644 index 16165f2..0000000 --- a/database/table/rolepermissions.go +++ /dev/null @@ -1,77 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type RolePermissions struct { - GuildId uint64 `gorm:"column:GUILDID"` - RoleId uint64 `gorm:"column:ROLEID"` - Support bool `gorm:"column:ISSUPPORT"` - Admin bool `gorm:"column:ISADMIN"` -} - -func (RolePermissions) TableName() string { - return "role_permissions" -} - -func IsSupportRole(guildId, roleId uint64, ch chan bool) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).First(&node) - ch <- node.Support -} - -func IsAdminRole(guildId, roleId uint64, ch chan bool) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).First(&node) - ch <- node.Admin -} - -func GetAdminRoles(guildId uint64, ch chan []uint64) { - var nodes []RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, Admin: true}).Find(&nodes) - - ids := make([]uint64, 0) - for _, node := range nodes { - ids = append(ids, node.RoleId) - } - - ch <- ids -} - -func GetSupportRoles(guildId uint64, ch chan []uint64) { - var nodes []RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, Support: true, Admin: false}).Find(&nodes) - - ids := make([]uint64, 0) - for _, node := range nodes { - ids = append(ids, node.RoleId) - } - - ch <- ids -} - -func AddAdminRole(guildId, roleId uint64) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).Assign(RolePermissions{Admin: true, Support: true}).FirstOrCreate(&node) -} - -func AddSupportRole(guildId, roleId uint64) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).Assign(RolePermissions{Support: true}).FirstOrCreate(&node) -} - -func RemoveAdminRole(guildId, roleId uint64) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).Take(&node) - database.Database.Model(&node).Where("GUILDID = ? AND ROLEID = ?", guildId, roleId).Update("ISADMIN", false) -} - -func RemoveSupportRole(guildId, roleId uint64) { - var node RolePermissions - database.Database.Where(RolePermissions{GuildId: guildId, RoleId: roleId}).Take(&node) - database.Database.Model(&node).Where("GUILDID = ? AND ROLEID = ?", guildId, roleId).Updates(map[string]interface{}{ - "ISADMIN": false, - "ISSUPPORT": false, - }) -} diff --git a/database/table/tags.go b/database/table/tags.go deleted file mode 100644 index 43ac2a3..0000000 --- a/database/table/tags.go +++ /dev/null @@ -1,42 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" - uuid "github.com/satori/go.uuid" -) - -type Tag struct { - Uuid string `gorm:"column:UUID;type:varchar(36);unique;primary_key"` - Id string `gorm:"column:ID;type:varchar(16)"` - Guild uint64 `gorm:"column:GUILDID"` - Content string `gorm:"column:TEXT;type:TEXT"` -} - -func (Tag) TableName() string { - return "cannedresponses" -} - -func GetTag(guild uint64, id string, ch chan string) { - var node Tag - database.Database.Where(Tag{Id: id, Guild: guild}).Take(&node) - ch <- node.Content -} - -func GetTags(guild uint64, ch chan []Tag) { - var rows []Tag - database.Database.Where(Tag{Guild: guild}).Find(&rows) - ch <- rows -} - -func AddTag(guild uint64, id string, content string) error { - return database.Database.Create(&Tag{ - Uuid: uuid.NewV4().String(), - Id: id, - Guild: guild, - Content: content, - }).Error -} - -func DeleteTag(guild uint64, id string) error { - return database.Database.Where(Tag{Id: id, Guild: guild}).Delete(&Tag{}).Error -} diff --git a/database/table/ticketarchive.go b/database/table/ticketarchive.go deleted file mode 100644 index 040abc8..0000000 --- a/database/table/ticketarchive.go +++ /dev/null @@ -1,50 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type TicketArchive struct { - Uuid string `gorm:"column:UUID;type:varchar(36)"` - Guild uint64 `gorm:"column:GUILDID"` - User uint64 `gorm:"column:USERID"` - Username string `gorm:"column:USERNAME;type:varchar(32)"` - TicketId int `gorm:"column:TICKETID"` - CdnUrl string `gorm:"column:CDNURL;type:varchar(100)"` -} - -func (TicketArchive) TableName() string { - return "ticketarchive" -} - -func GetTicketArchives(guildId uint64) []TicketArchive { - var archives []TicketArchive - database.Database.Where(&TicketArchive{Guild: guildId}).Order("TICKETID desc").Find(&archives) - - return archives -} - -func GetFilteredTicketArchives(guildId uint64, userId uint64, username string, ticketId int) []TicketArchive { - var archives []TicketArchive - - query := database.Database.Where(&TicketArchive{Guild: guildId}) - if userId != 0 { - query = query.Where(&TicketArchive{User: userId}) - } - if username != "" { - query = query.Where(&TicketArchive{Username: username}) - } - if ticketId != 0 { - query = query.Where(&TicketArchive{TicketId: ticketId}) - } - - query.Order("TICKETID desc").Find(&archives) - - return archives -} - -func GetCdnUrl(guildId uint64, uuid string) string { - var archive TicketArchive - database.Database.Where(&TicketArchive{Guild: guildId, Uuid: uuid}).First(&archive) - return archive.CdnUrl -} diff --git a/database/table/ticketlimit.go b/database/table/ticketlimit.go deleted file mode 100644 index 874a47a..0000000 --- a/database/table/ticketlimit.go +++ /dev/null @@ -1,24 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type TicketLimit struct { - GuildId uint64 `gorm:"column:GUILDID"` - Limit int `gorm:"column:TICKETLIMIT"` -} - -func (TicketLimit) TableName() string { - return "ticketlimit" -} - -func UpdateTicketLimit(guildId uint64, limit int) { - database.Database.Where(&TicketLimit{GuildId: guildId}).Assign(&TicketLimit{Limit: limit}).FirstOrCreate(&TicketLimit{}) -} - -func GetTicketLimit(guildId uint64, ch chan int) { - limit := TicketLimit{Limit: 5} - database.Database.Where(&TicketLimit{GuildId: guildId}).First(&limit) - ch <- limit.Limit -} diff --git a/database/table/tickets.go b/database/table/tickets.go deleted file mode 100644 index 757427c..0000000 --- a/database/table/tickets.go +++ /dev/null @@ -1,54 +0,0 @@ -package table - -import "github.com/TicketsBot/GoPanel/database" - -type Ticket struct { - Uuid string `gorm:"column:UUID;type:varchar(36);primary_key"` - TicketId int `gorm:"column:ID"` - Guild uint64 `gorm:"column:GUILDID"` - Channel uint64 `gorm:"column:CHANNELID"` - Owner uint64 `gorm:"column:OWNERID"` - Members string `gorm:"column:MEMBERS;type:text"` - IsOpen bool `gorm:"column:OPEN"` - OpenTime int64 `gorm:"column:OPENTIME"` -} - -func (Ticket) TableName() string { - return "tickets" -} - -func GetTickets(guild uint64) []Ticket { - var tickets []Ticket - database.Database.Where(&Ticket{Guild: guild}).Order("ID asc").Find(&tickets) - return tickets -} - -func GetClosedTickets(guildId uint64) []Ticket { - var tickets []Ticket - database.Database.Where(&Ticket{Guild: guildId}).Where("OPEN = 0").Order("ID desc").Find(&tickets) - return tickets -} - -func GetClosedTicketsByUserId(guildId uint64, userIds []uint64) []Ticket { - var tickets []Ticket - database.Database.Where(&Ticket{Guild: guildId}).Where("OPEN = 0").Where("OWNERID IN (?)", userIds).Order("ID desc").Find(&tickets) - return tickets -} - -func GetOpenTickets(guild uint64) []Ticket { - var tickets []Ticket - database.Database.Where(&Ticket{Guild: guild, IsOpen: true}).Order("ID desc").Find(&tickets) - return tickets -} - -func GetTicket(uuid string, ch chan Ticket) { - var ticket Ticket - database.Database.Where(&Ticket{Uuid: uuid}).First(&ticket) - ch <- ticket -} - -func GetTicketById(guild uint64, id int, ch chan Ticket) { - var ticket Ticket - database.Database.Where(&Ticket{Guild: guild, TicketId: id}).First(&ticket) - ch <- ticket -} diff --git a/database/table/ticketwebhook.go b/database/table/ticketwebhook.go deleted file mode 100644 index bfce1ed..0000000 --- a/database/table/ticketwebhook.go +++ /dev/null @@ -1,31 +0,0 @@ -package table - -import "github.com/TicketsBot/GoPanel/database" - -type TicketWebhook struct { - Uuid string `gorm:"column:UUID;type:varchar(36);unique;primary_key"` - WebhookUrl string `gorm:"column:CDNURL;type:varchar(200)"` -} - -func (TicketWebhook) TableName() string { - return "webhooks" -} - -func (w *TicketWebhook) AddWebhook() { - database.Database.Create(w) -} - -func DeleteWebhookByUuid(uuid string) { - database.Database.Where(TicketWebhook{Uuid: uuid}).Delete(TicketWebhook{}) -} - -func GetWebhookByUuid(uuid string, res chan *string) { - var row TicketWebhook - database.Database.Where(TicketWebhook{Uuid: uuid}).Take(&row) - - if row.WebhookUrl == "" { - res <- nil - } else { - res <- &row.WebhookUrl - } -} diff --git a/database/table/userscanclose.go b/database/table/userscanclose.go deleted file mode 100644 index f324925..0000000 --- a/database/table/userscanclose.go +++ /dev/null @@ -1,27 +0,0 @@ -package table - -import "github.com/TicketsBot/GoPanel/database" - -type UserCanClose struct { - Guild uint64 `gorm:"column:GUILDID;unique;primary_key"` - CanClose *bool `gorm:"column:CANCLOSE"` -} - -func (UserCanClose) TableName() string { - return "usercanclose" -} - -func IsUserCanClose(guild uint64, ch chan bool) { - var node UserCanClose - database.Database.Where(UserCanClose{Guild: guild}).First(&node) - - if node.CanClose == nil { - ch <- true - } else { - ch <- *node.CanClose - } -} - -func SetUserCanClose(guild uint64, value bool) { - database.Database.Where(&UserCanClose{Guild: guild}).Assign(&UserCanClose{CanClose: &value}).FirstOrCreate(&UserCanClose{}) -} diff --git a/database/table/votes.go b/database/table/votes.go deleted file mode 100644 index 61594cd..0000000 --- a/database/table/votes.go +++ /dev/null @@ -1,22 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" - "time" -) - -type Votes struct { - Id uint64 `gorm:"type:bigint;unique_index;primary_key"` - VoteTime time.Time -} - -func (Votes) TableName() string { - return "votes" -} - -func HasVoted(owner uint64, ch chan bool) { - var node Votes - database.Database.Where(Votes{Id: owner}).First(&node) - - ch <- time.Now().Sub(node.VoteTime) < 24*time.Hour -} diff --git a/database/table/welcomemessage.go b/database/table/welcomemessage.go deleted file mode 100644 index 6b4187d..0000000 --- a/database/table/welcomemessage.go +++ /dev/null @@ -1,24 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" -) - -type WelcomeMessage struct { - GuildId uint64 `gorm:"column:GUILDID"` - Message string `gorm:"column:MESSAGE;type:text"` -} - -func (WelcomeMessage) TableName() string { - return "welcomemessages" -} - -func UpdateWelcomeMessage(guildId uint64, message string) { - database.Database.Where(&WelcomeMessage{GuildId: guildId}).Assign(&WelcomeMessage{Message: message}).FirstOrCreate(&WelcomeMessage{}) -} - -func GetWelcomeMessage(guildId uint64, ch chan string) { - message := WelcomeMessage{Message: "No message specified"} - database.Database.Where(&WelcomeMessage{GuildId: guildId}).First(&message) - ch <- message.Message -} diff --git a/go.mod b/go.mod index 15833c9..75f16a0 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.14 require ( github.com/BurntSushi/toml v0.3.1 github.com/TicketsBot/archiverclient v0.0.0-20200425115930-0ca198cc8306 + github.com/TicketsBot/database v0.0.0-20200511174804-50ba8d78e1f9 github.com/apex/log v1.1.2 github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible @@ -14,6 +15,7 @@ require ( github.com/gin-gonic/gin v1.6.2 github.com/go-redis/redis v6.15.7+incompatible github.com/go-sql-driver/mysql v1.5.0 + github.com/gofrs/uuid v3.3.0+incompatible github.com/gorilla/sessions v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 github.com/jackc/pgx/v4 v4.6.0 @@ -21,8 +23,9 @@ require ( github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c github.com/pkg/errors v0.9.1 github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 - github.com/rxdn/gdl v0.0.0-20200421193445-f200b9f466d7 + github.com/rxdn/gdl v0.0.0-20200511170555-8ab2206d70df github.com/satori/go.uuid v1.2.0 + github.com/sirupsen/logrus v1.5.0 github.com/ulule/limiter/v3 v3.5.0 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a ) diff --git a/messagequeue/panelcreate.go b/messagequeue/panelcreate.go index b079c52..ed2b920 100644 --- a/messagequeue/panelcreate.go +++ b/messagequeue/panelcreate.go @@ -2,11 +2,11 @@ package messagequeue import ( "encoding/json" - "github.com/TicketsBot/GoPanel/database/table" + "github.com/TicketsBot/database" "github.com/apex/log" ) -func (c *RedisClient) PublishPanelCreate(settings table.Panel) { +func (c *RedisClient) PublishPanelCreate(settings database.Panel) { encoded, err := json.Marshal(settings); if err != nil { log.Error(err.Error()) return diff --git a/messagequeue/ticketclose.go b/messagequeue/ticketclose.go index 3e2f162..85c931b 100644 --- a/messagequeue/ticketclose.go +++ b/messagequeue/ticketclose.go @@ -6,23 +6,25 @@ import ( ) type TicketCloseMessage struct { - Uuid string - User uint64 - Reason string + GuildId uint64 + TicketId int + User uint64 + Reason string } -func (c *RedisClient) PublishTicketClose(ticket string, userId uint64, reason string) { +func (c *RedisClient) PublishTicketClose(guildId uint64, ticketId int, userId uint64, reason string) { settings := TicketCloseMessage{ - Uuid: ticket, - User: userId, - Reason: reason, + GuildId: guildId, + TicketId: ticketId, + User: userId, + Reason: reason, } - encoded, err := json.Marshal(settings); if err != nil { + encoded, err := json.Marshal(settings) + if err != nil { log.Error(err.Error()) return } c.Publish("tickets:close", string(encoded)) } - diff --git a/public/templates/views/logs.tmpl b/public/templates/views/logs.tmpl index 0ae349c..8166c11 100644 --- a/public/templates/views/logs.tmpl +++ b/public/templates/views/logs.tmpl @@ -84,13 +84,16 @@ - + diff --git a/public/templates/views/modmaillogs.tmpl b/public/templates/views/modmaillogs.tmpl index 193aa7f..f2f4e07 100644 --- a/public/templates/views/modmaillogs.tmpl +++ b/public/templates/views/modmaillogs.tmpl @@ -84,6 +84,7 @@ diff --git a/public/templates/views/panels.tmpl b/public/templates/views/panels.tmpl index f0af675..60e9400 100644 --- a/public/templates/views/panels.tmpl +++ b/public/templates/views/panels.tmpl @@ -155,6 +155,7 @@ const res = await axios.put('/api/{{.guildId}}/panels', data); if (res.status === 200 && res.data.success) { + data.message_id = res.data.message_id; appendPanel(data, await getChannels()); showToast('Success', 'Panel created successfully') } else { diff --git a/public/templates/views/settings.tmpl b/public/templates/views/settings.tmpl index f94ee70..3b651f8 100644 --- a/public/templates/views/settings.tmpl +++ b/public/templates/views/settings.tmpl @@ -39,7 +39,7 @@
+ style="resize: none">
diff --git a/public/templates/views/tags.tmpl b/public/templates/views/tags.tmpl index 98ca522..646bd1a 100644 --- a/public/templates/views/tags.tmpl +++ b/public/templates/views/tags.tmpl @@ -76,7 +76,7 @@ const res = await axios.put('/api/{{.guildId}}/tags', data); - if (res.status === 200 && res.data.success) { + if (res.status === 200) { document.getElementById('id').value = ''; document.getElementById('content').value = ''; @@ -96,14 +96,14 @@ } } - function appendTag(tag) { + function appendTag(id, content) { const container = document.getElementById('tag-container'); const tr = document.createElement('tr'); - tr.id = tag.id; + tr.id = id; - appendTd(tr, tag.id); - appendTd(tr, tag.content).classList.add('tag-content'); - appendButton(tr, 'Delete', () => { deleteTag(tag.id); }); + appendTd(tr, id); + appendTd(tr, content).classList.add('tag-content'); + appendButton(tr, 'Delete', () => { deleteTag(id); }); container.appendChild(tr); } @@ -112,8 +112,8 @@ const res = await axios.get('/api/{{.guildId}}/tags'); if (res.status === 200) { - for (tag of res.data) { - appendTag(tag); + for (const [id, content] of Object.entries(res.data)) { + appendTag(id, content); } } } diff --git a/public/templates/views/ticketlist.tmpl b/public/templates/views/ticketlist.tmpl index 8bfe9b9..d7cd17a 100644 --- a/public/templates/views/ticketlist.tmpl +++ b/public/templates/views/ticketlist.tmpl @@ -39,7 +39,7 @@ const members = ticket.members.map(member => `${member.username}#${member.discrim}`).join(', '); appendTd(tr, members); - appendButton(tr, 'View', () => { console.log(ticket); location.href = '/manage/{{.guildId}}/tickets/view/' + ticket.uuid }); + appendButton(tr, 'View', () => { console.log(ticket); location.href = '/manage/{{.guildId}}/tickets/view/' + ticket.ticketId }); container.appendChild(tr); } diff --git a/public/templates/views/ticketview.tmpl b/public/templates/views/ticketview.tmpl index 7526b21..a924187 100644 --- a/public/templates/views/ticketview.tmpl +++ b/public/templates/views/ticketview.tmpl @@ -45,7 +45,7 @@ const reason = document.getElementById('reason').value; document.getElementById('reason').value = ''; - const res = await axios.delete('/api/{{.guildId}}/tickets/{{.uuid}}', { + const res = await axios.delete('/api/{{.guildId}}/tickets/{{.ticketId}}', { data: { reason: reason } @@ -86,20 +86,20 @@ async function loadData() { const premium = await isPremium(); - const res = await axios.get('/api/{{.guildId}}/tickets/{{.uuid}}'); + const res = await axios.get('/api/{{.guildId}}/tickets/{{.ticketId}}'); if (res.status === 200 && res.data.success) { const data = res.data; - document.getElementById('channel-name').innerText = `#ticket-${data.ticket.TicketId}`; + document.getElementById('channel-name').innerText = `#ticket-${data.ticket.Id}`; await appendMessages(data.messages); - startWebsocket(data.ticket.TicketId); + startWebsocket(data.ticket.Id); } else { showToast('Error', res.data.error); } const el = document.getElementById('message'); if (premium) { - el.placeholder = `Message #ticket-${res.data.ticket.TicketId}`; + el.placeholder = `Message #ticket-${res.data.ticket.Id}`; } else { el.disabled = true; el.placeholder = 'Premium users get live messages and can respond through webchat' @@ -110,12 +110,13 @@