Finish postgres port
This commit is contained in:
parent
8ed1bec46a
commit
bf7dc7cf09
@ -1,11 +1,14 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type userData struct {
|
type userData struct {
|
||||||
@ -16,18 +19,38 @@ type userData struct {
|
|||||||
func GetBlacklistHandler(ctx *gin.Context) {
|
func GetBlacklistHandler(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
|
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)
|
data := make(map[string]userData)
|
||||||
|
var lock sync.Mutex
|
||||||
|
|
||||||
blacklistedUsers := table.GetBlacklistNodes(guildId)
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
for _, row := range blacklistedUsers {
|
for _, userId := range blacklistedUsers {
|
||||||
formattedId := strconv.FormatUint(row.User, 10)
|
group.Go(func() error {
|
||||||
user, _ := cache.Instance.GetUser(row.User)
|
user, _ := cache.Instance.GetUser(userId)
|
||||||
|
|
||||||
data[formattedId] = userData{
|
lock.Lock()
|
||||||
|
|
||||||
|
// JS cant do big ints
|
||||||
|
data[strconv.FormatUint(userId, 10)] = userData{
|
||||||
Username: user.Username,
|
Username: user.Username,
|
||||||
Discriminator: fmt.Sprintf("%04d", user.Discriminator),
|
Discriminator: fmt.Sprintf("%04d", user.Discriminator),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = group.Wait()
|
||||||
|
|
||||||
ctx.JSON(200, data)
|
ctx.JSON(200, data)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jackc/pgx/v4"
|
"github.com/jackc/pgx/v4"
|
||||||
@ -50,11 +50,15 @@ func AddBlacklistHandler(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Don't blacklist staff or guild owner
|
// TODO: Don't blacklist staff or guild owner
|
||||||
|
if err = database.Client.Blacklist.Add(guildId, targetId); err == nil {
|
||||||
go table.AddBlacklist(guildId, targetId)
|
|
||||||
|
|
||||||
ctx.JSON(200, gin.H{
|
ctx.JSON(200, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"user_id": strconv.FormatUint(targetId, 10),
|
"user_id": strconv.FormatUint(targetId, 10),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
ctx.JSON(500, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@ -18,9 +18,14 @@ func RemoveBlacklistHandler(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.RemoveBlacklist(guildId, userId)
|
if err := database.Client.Blacklist.Remove(guildId, userId); err == nil {
|
||||||
|
|
||||||
ctx.JSON(200, gin.H{
|
ctx.JSON(200, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
ctx.JSON(200, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"err": err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/messagequeue"
|
"github.com/TicketsBot/GoPanel/messagequeue"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type closeBody struct {
|
type closeBody struct {
|
||||||
@ -13,7 +14,15 @@ type closeBody struct {
|
|||||||
func CloseTicket(ctx *gin.Context) {
|
func CloseTicket(ctx *gin.Context) {
|
||||||
userId := ctx.Keys["userid"].(uint64)
|
userId := ctx.Keys["userid"].(uint64)
|
||||||
guildId := ctx.Keys["guildid"].(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
|
var data closeBody
|
||||||
if err := ctx.BindJSON(&data); err != nil {
|
if err := ctx.BindJSON(&data); err != nil {
|
||||||
@ -24,12 +33,18 @@ func CloseTicket(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the ticket exists
|
// Get the ticket struct
|
||||||
ticketChan := make(chan table.Ticket)
|
ticket, err := database.Client.Tickets.Get(ticketId, guildId)
|
||||||
go table.GetTicket(uuid, ticketChan)
|
if err != nil {
|
||||||
ticket := <-ticketChan
|
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{
|
ctx.AbortWithStatusJSON(404, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"error": "Ticket does not exist",
|
"error": "Ticket does not exist",
|
||||||
@ -37,7 +52,7 @@ func CloseTicket(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ticket.Guild != guildId {
|
if ticket.GuildId != guildId {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"error": "Guild ID does not matched",
|
"error": "Guild ID does not matched",
|
||||||
@ -45,7 +60,7 @@ func CloseTicket(ctx *gin.Context) {
|
|||||||
return
|
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{
|
ctx.JSON(200, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
|
@ -3,7 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
@ -18,13 +18,27 @@ var MentionRegex, _ = regexp.Compile("<@(\\d+)>")
|
|||||||
|
|
||||||
func GetTicket(ctx *gin.Context) {
|
func GetTicket(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
uuid := ctx.Param("uuid")
|
|
||||||
|
|
||||||
ticketChan := make(chan table.Ticket)
|
ticketId, err := strconv.Atoi(ctx.Param("ticketId"))
|
||||||
go table.GetTicket(uuid, ticketChan)
|
if err != nil {
|
||||||
ticket := <-ticketChan
|
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{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Guild ID doesn't match",
|
"error": "Guild ID doesn't match",
|
||||||
@ -32,7 +46,7 @@ func GetTicket(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ticket.IsOpen {
|
if !ticket.Open {
|
||||||
ctx.AbortWithStatusJSON(404, gin.H{
|
ctx.AbortWithStatusJSON(404, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Ticket does not exist",
|
"error": "Ticket does not exist",
|
||||||
@ -40,8 +54,16 @@ func GetTicket(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ticket.ChannelId == nil {
|
||||||
|
ctx.AbortWithStatusJSON(404, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"error": "Ticket channel does not exist",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get messages
|
// 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
|
// Format messages, exclude unneeded data
|
||||||
messagesFormatted := make([]map[string]interface{}, 0)
|
messagesFormatted := make([]map[string]interface{}, 0)
|
||||||
|
@ -1,49 +1,72 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetTickets(ctx *gin.Context) {
|
func GetTickets(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
tickets := table.GetOpenTickets(guildId)
|
tickets, err := database.Client.Tickets.GetGuildOpenTickets(guildId)
|
||||||
ticketsFormatted := make([]map[string]interface{}, 0)
|
if err != nil {
|
||||||
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
for _, ticket := range tickets {
|
"success": false,
|
||||||
membersFormatted := make([]map[string]interface{}, 0)
|
"error": err.Error(),
|
||||||
for index, memberIdStr := range strings.Split(ticket.Members, ",") {
|
})
|
||||||
if memberId, err := strconv.ParseUint(memberIdStr, 10, 64); err == nil {
|
return
|
||||||
if memberId != 0 {
|
|
||||||
var separator string
|
|
||||||
if index != len(strings.Split(ticket.Members, ","))-1 {
|
|
||||||
separator = ", "
|
|
||||||
}
|
}
|
||||||
|
|
||||||
member, _ := cache.Instance.GetUser(memberId)
|
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{}{
|
membersFormatted = append(membersFormatted, map[string]interface{}{
|
||||||
"username": member.Username,
|
"id": strconv.FormatUint(userId, 10),
|
||||||
"discrim": fmt.Sprintf("%04d", member.Discriminator),
|
"username": user.Username,
|
||||||
"sep": separator,
|
"discrim": fmt.Sprintf("%04d", user.Discriminator),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
owner, _ := cache.Instance.GetUser(ticket.Owner)
|
owner, _ := cache.Instance.GetUser(ticket.UserId)
|
||||||
ticketsFormatted = append(ticketsFormatted, map[string]interface{}{
|
|
||||||
"uuid": ticket.Uuid,
|
ticketsFormatted[len(tickets) - 1 - i] = map[string]interface{}{
|
||||||
"ticketId": ticket.TicketId,
|
"ticketId": ticket.Id,
|
||||||
"username": owner.Username,
|
"username": owner.Username,
|
||||||
"discrim": fmt.Sprintf("%04d", owner.Discriminator),
|
"discrim": fmt.Sprintf("%04d", owner.Discriminator),
|
||||||
"members": membersFormatted,
|
"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)
|
ctx.JSON(200, ticketsFormatted)
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,48 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/objects/guild"
|
"github.com/rxdn/gdl/objects/guild"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type wrappedGuild struct {
|
||||||
|
Id uint64 `json:"id,string"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
func GetGuilds(ctx *gin.Context) {
|
func GetGuilds(ctx *gin.Context) {
|
||||||
userId := ctx.Keys["userid"].(uint64)
|
userId := ctx.Keys["userid"].(uint64)
|
||||||
|
|
||||||
userGuilds := table.GetGuilds(userId)
|
guilds, err := database.Client.UserGuilds.Get(userId)
|
||||||
adminGuilds := make([]guild.Guild, 0)
|
if err != nil {
|
||||||
for _, g := range userGuilds {
|
ctx.JSON(500, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
adminGuilds := make([]wrappedGuild, 0)
|
||||||
|
for _, g := range guilds {
|
||||||
fakeGuild := guild.Guild{
|
fakeGuild := guild.Guild{
|
||||||
Id: g.Id,
|
Id: g.GuildId,
|
||||||
OwnerId: g.OwnerId,
|
Owner: g.Owner,
|
||||||
Permissions: g.Permissions,
|
Permissions: int(g.UserPermissions),
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Owner {
|
||||||
|
fakeGuild.OwnerId = userId
|
||||||
}
|
}
|
||||||
|
|
||||||
isAdmin := make(chan bool)
|
isAdmin := make(chan bool)
|
||||||
go utils.IsAdmin(fakeGuild, userId, isAdmin)
|
go utils.IsAdmin(fakeGuild, userId, isAdmin)
|
||||||
if <-isAdmin {
|
if <-isAdmin {
|
||||||
adminGuilds = append(adminGuilds, g)
|
adminGuilds = append(adminGuilds, wrappedGuild{
|
||||||
|
Id: g.GuildId,
|
||||||
|
Name: g.Name,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
"github.com/TicketsBot/database"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/rest"
|
"github.com/rxdn/gdl/rest"
|
||||||
@ -15,15 +16,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pageLimit = 30
|
pageLimit = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetLogs(ctx *gin.Context) {
|
func GetLogs(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
page, err := strconv.Atoi(ctx.Param("page"))
|
before, err := strconv.Atoi(ctx.Query("before"))
|
||||||
if page < 1 {
|
if before < 0 {
|
||||||
page = 1
|
before = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get ticket ID from URL
|
// Get ticket ID from URL
|
||||||
@ -32,15 +33,20 @@ func GetLogs(ctx *gin.Context) {
|
|||||||
ticketId, _ = strconv.Atoi(ctx.Query("ticketid"))
|
ticketId, _ = strconv.Atoi(ctx.Query("ticketid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var tickets []table.Ticket
|
var tickets []database.Ticket
|
||||||
|
|
||||||
// Get tickets from DB
|
// Get tickets from DB
|
||||||
if ticketId > 0 {
|
if ticketId > 0 {
|
||||||
ticketChan := make(chan table.Ticket)
|
ticket, err := dbclient.Client.Tickets.Get(ticketId, guildId)
|
||||||
go table.GetTicketById(guildId, ticketId, ticketChan)
|
if err != nil {
|
||||||
ticket := <-ticketChan
|
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)
|
tickets = append(tickets, ticket)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -76,25 +82,27 @@ func GetLogs(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Query("userid") != "" || ctx.Query("username") != "" {
|
if ctx.Query("userid") != "" || ctx.Query("username") != "" {
|
||||||
tickets = table.GetClosedTicketsByUserId(guildId, filteredIds)
|
tickets, err = dbclient.Client.Tickets.GetMemberClosedTickets(guildId, filteredIds, pageLimit, before)
|
||||||
} else {
|
} 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
|
// Select 30 logs + format them
|
||||||
formattedLogs := make([]map[string]interface{}, 0)
|
formattedLogs := make([]map[string]interface{}, 0)
|
||||||
for i := (page - 1) * pageLimit; i < (page-1)*pageLimit+pageLimit; i++ {
|
for _, ticket := range tickets {
|
||||||
if i >= len(tickets) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
ticket := tickets[i]
|
|
||||||
|
|
||||||
// get username
|
// get username
|
||||||
user, found := cache.Instance.GetUser(ticket.Owner)
|
user, found := cache.Instance.GetUser(ticket.UserId)
|
||||||
if !found {
|
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 {
|
if err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
}
|
}
|
||||||
@ -102,8 +110,8 @@ func GetLogs(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
formattedLogs = append(formattedLogs, map[string]interface{}{
|
formattedLogs = append(formattedLogs, map[string]interface{}{
|
||||||
"ticketid": ticket.TicketId,
|
"ticketid": ticket.Id,
|
||||||
"userid": strconv.FormatUint(ticket.Owner, 10),
|
"userid": strconv.FormatUint(ticket.UserId, 10),
|
||||||
"username": user.Username,
|
"username": user.Username,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
|
"github.com/TicketsBot/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gofrs/uuid"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@ -18,15 +20,18 @@ type wrappedModLog struct {
|
|||||||
UserId uint64 `json:"user_id,string"`
|
UserId uint64 `json:"user_id,string"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Take after param
|
||||||
func GetModmailLogs(ctx *gin.Context) {
|
func GetModmailLogs(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
page, err := strconv.Atoi(ctx.Param("page"))
|
after, err := uuid.FromString(ctx.Query("after"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.AbortWithStatusJSON(400, gin.H{
|
after = uuid.Nil
|
||||||
"success": false,
|
}
|
||||||
"error": err.Error(),
|
|
||||||
})
|
before, err := uuid.FromString(ctx.Query("before"))
|
||||||
|
if err != nil {
|
||||||
|
before = uuid.Nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter
|
// filter
|
||||||
@ -53,27 +58,28 @@ func GetModmailLogs(ctx *gin.Context) {
|
|||||||
|
|
||||||
shouldFilter := userId > 0
|
shouldFilter := userId > 0
|
||||||
|
|
||||||
start := pageLimit * (page - 1)
|
|
||||||
end := start + pageLimit - 1
|
|
||||||
|
|
||||||
wrapped := make([]wrappedModLog, 0)
|
wrapped := make([]wrappedModLog, 0)
|
||||||
|
|
||||||
var archives []table.ModMailArchive
|
var archives []database.ModmailArchive
|
||||||
if shouldFilter {
|
if shouldFilter {
|
||||||
archivesCh := make(chan []table.ModMailArchive)
|
archives, err = dbclient.Client.ModmailArchive.GetByMember(guildId, userId, pageLimit, after, before)
|
||||||
go table.GetModmailArchivesByUser(userId, guildId, archivesCh)
|
|
||||||
archives = <-archivesCh
|
|
||||||
} else {
|
} else {
|
||||||
archivesCh := make(chan []table.ModMailArchive)
|
archives, err = dbclient.Client.ModmailArchive.GetByGuild(guildId, pageLimit, after, before)
|
||||||
go table.GetModmailArchivesByGuild(guildId, archivesCh)
|
|
||||||
archives = <-archivesCh
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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{
|
wrapped = append(wrapped, wrappedModLog{
|
||||||
Uuid: archives[i].Uuid,
|
Uuid: archive.Uuid.String(),
|
||||||
GuildId: archives[i].Guild,
|
GuildId: archive.GuildId,
|
||||||
UserId: archives[i].User,
|
UserId: archive.UserId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
"github.com/TicketsBot/GoPanel/messagequeue"
|
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
"github.com/TicketsBot/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/objects/channel"
|
"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"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,12 +32,19 @@ func CreatePanel(ctx *gin.Context) {
|
|||||||
data.MessageId = 0
|
data.MessageId = 0
|
||||||
|
|
||||||
// Check panel quota
|
// Check panel quota
|
||||||
premium := make(chan bool)
|
premiumChan := make(chan bool)
|
||||||
go utils.IsPremiumGuild(guildId, premium)
|
go utils.IsPremiumGuild(guildId, premiumChan)
|
||||||
if !<-premium {
|
isPremium := <-premiumChan
|
||||||
panels := make(chan []table.Panel)
|
if !isPremium {
|
||||||
go table.GetPanelsByGuild(guildId, panels)
|
panels, err := dbclient.Client.Panel.GetByGuild(guildId)
|
||||||
if len(<-panels) > 0 {
|
if err != nil {
|
||||||
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(panels) > 0 {
|
||||||
ctx.AbortWithStatusJSON(402, gin.H{
|
ctx.AbortWithStatusJSON(402, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "You have exceeded your panel quota. Purchase premium to unlock more panels.",
|
"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{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Panel titles must be between 1 - 255 characters in length",
|
"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{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Panel content must be between 1 - 1024 characters in length",
|
"error": "Panel content must be between 1 - 1024 characters in length",
|
||||||
})
|
})
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
channels := cache.Instance.GetGuildChannels(guildId)
|
channels := cache.Instance.GetGuildChannels(guildId)
|
||||||
|
|
||||||
if !data.verifyChannel(channels) {
|
if !p.verifyChannel(channels) {
|
||||||
ctx.AbortWithStatusJSON(400, gin.H{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Invalid channel",
|
"error": "Invalid channel",
|
||||||
})
|
})
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !data.verifyCategory(channels) {
|
if !p.verifyCategory(channels) {
|
||||||
ctx.AbortWithStatusJSON(400, gin.H{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Invalid channel category",
|
"error": "Invalid channel category",
|
||||||
})
|
})
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
emoji, validEmoji := data.getEmoji()
|
_, validEmoji := p.getEmoji()
|
||||||
if !validEmoji {
|
if !validEmoji {
|
||||||
ctx.AbortWithStatusJSON(400, gin.H{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Invalid emoji. Simply use the emoji's name from Discord.",
|
"error": "Invalid emoji. Simply use the emoji's name from Discord.",
|
||||||
})
|
})
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move panel create logic here
|
return true
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *panel) verifyTitle() bool {
|
func (p *panel) verifyTitle() bool {
|
||||||
@ -136,3 +205,24 @@ func (p *panel) verifyCategory(channels []channel.Channel) bool {
|
|||||||
|
|
||||||
return valid
|
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
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/rest"
|
"github.com/rxdn/gdl/rest"
|
||||||
@ -21,11 +21,16 @@ func DeletePanel(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify panel belongs to guild
|
panel, err := database.Client.Panel.Get(messageId)
|
||||||
panelChan := make(chan table.Panel)
|
if err != nil {
|
||||||
go table.GetPanel(messageId, panelChan)
|
ctx.JSON(500, gin.H{
|
||||||
panel := <-panelChan
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify panel belongs to guild
|
||||||
if panel.GuildId != guildId {
|
if panel.GuildId != guildId {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
@ -34,8 +39,21 @@ func DeletePanel(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.DeletePanel(messageId)
|
if err := database.Client.Panel.Delete(messageId); err != nil {
|
||||||
go rest.DeleteMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, panel.ChannelId, panel.MessageId)
|
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{
|
ctx.JSON(200, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,9 +18,14 @@ type panel struct {
|
|||||||
func ListPanels(ctx *gin.Context) {
|
func ListPanels(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
panelsChan := make(chan []table.Panel)
|
panels, err := database.Client.Panel.GetByGuild(guildId)
|
||||||
go table.GetPanelsByGuild(guildId, panelsChan)
|
if err != nil {
|
||||||
panels := <-panelsChan
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
wrapped := make([]panel, len(panels))
|
wrapped := make([]panel, len(panels))
|
||||||
|
|
||||||
@ -30,7 +35,7 @@ func ListPanels(ctx *gin.Context) {
|
|||||||
MessageId: p.MessageId,
|
MessageId: p.MessageId,
|
||||||
Title: p.Title,
|
Title: p.Title,
|
||||||
Content: p.Content,
|
Content: p.Content,
|
||||||
Colour: p.Colour,
|
Colour: uint32(p.Colour),
|
||||||
CategoryId: p.TargetCategory,
|
CategoryId: p.TargetCategory,
|
||||||
Emote: p.ReactionEmote,
|
Emote: p.ReactionEmote,
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/rest"
|
"github.com/rxdn/gdl/rest"
|
||||||
"net/http"
|
"github.com/rxdn/gdl/rest/request"
|
||||||
"time"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sendMessageBody struct {
|
type sendMessageBody struct {
|
||||||
@ -23,6 +21,16 @@ func SendMessage(ctx *gin.Context) {
|
|||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
userId := ctx.Keys["userid"].(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
|
var body sendMessageBody
|
||||||
if err := ctx.BindJSON(&body); err != nil {
|
if err := ctx.BindJSON(&body); err != nil {
|
||||||
ctx.AbortWithStatusJSON(400, gin.H{
|
ctx.AbortWithStatusJSON(400, gin.H{
|
||||||
@ -44,12 +52,10 @@ func SendMessage(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get ticket
|
// Get ticket
|
||||||
ticketChan := make(chan table.Ticket)
|
ticket, err := database.Client.Tickets.Get(ticketId, guildId)
|
||||||
go table.GetTicket(ctx.Param("uuid"), ticketChan)
|
|
||||||
ticket := <-ticketChan
|
|
||||||
|
|
||||||
// Verify the ticket exists
|
// Verify the ticket exists
|
||||||
if ticket.TicketId == 0 {
|
if ticket.UserId == 0 {
|
||||||
ctx.AbortWithStatusJSON(404, gin.H{
|
ctx.AbortWithStatusJSON(404, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Ticket not found",
|
"error": "Ticket not found",
|
||||||
@ -58,7 +64,7 @@ func SendMessage(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the user has permission to send to this guild
|
// Verify the user has permission to send to this guild
|
||||||
if ticket.Guild != guildId {
|
if ticket.GuildId != guildId {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "Guild ID doesn't match",
|
"error": "Guild ID doesn't match",
|
||||||
@ -73,60 +79,61 @@ func SendMessage(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Preferably send via a webhook
|
// Preferably send via a webhook
|
||||||
webhookChan := make(chan *string)
|
webhook, err := database.Client.Webhooks.Get(guildId, ticketId)
|
||||||
go table.GetWebhookByUuid(ticket.Uuid, webhookChan)
|
if err != nil {
|
||||||
webhook := <-webhookChan
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
|
"success": false,
|
||||||
success := false
|
"error": err.Error(),
|
||||||
if webhook != nil {
|
})
|
||||||
// TODO: Use gdl execute webhook wrapper
|
return
|
||||||
success = executeWebhook(ticket.Uuid, *webhook, body.Message, user.Username, user.AvatarUrl(256))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
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),
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
body.Message = fmt.Sprintf("**%s**: %s", user.Username, body.Message)
|
||||||
if len(body.Message) > 2000 {
|
if len(body.Message) > 2000 {
|
||||||
body.Message = body.Message[0:1999]
|
body.Message = body.Message[0:1999]
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.Channel, rest.CreateMessageData{Content: body.Message})
|
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{
|
ctx.JSON(200, gin.H{
|
||||||
"success": true,
|
"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
|
|
||||||
}
|
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"context"
|
||||||
|
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||||
|
"github.com/TicketsBot/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
Prefix string `json:"prefix"`
|
Prefix string `json:"prefix"`
|
||||||
WelcomeMessaage string `json:"welcome_message"`
|
WelcomeMessaage string `json:"welcome_message"`
|
||||||
TicketLimit int `json:"ticket_limit"`
|
TicketLimit uint8 `json:"ticket_limit"`
|
||||||
Category uint64 `json:"category,string"`
|
Category uint64 `json:"category,string"`
|
||||||
ArchiveChannel uint64 `json:"archive_channel,string"`
|
ArchiveChannel uint64 `json:"archive_channel,string"`
|
||||||
NamingScheme table.NamingScheme `json:"naming_scheme"`
|
NamingScheme database.NamingScheme `json:"naming_scheme"`
|
||||||
PingEveryone bool `json:"ping_everyone"`
|
PingEveryone bool `json:"ping_everyone"`
|
||||||
UsersCanClose bool `json:"users_can_close"`
|
UsersCanClose bool `json:"users_can_close"`
|
||||||
}
|
}
|
||||||
@ -19,38 +22,78 @@ type Settings struct {
|
|||||||
func GetSettingsHandler(ctx *gin.Context) {
|
func GetSettingsHandler(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
prefix := make(chan string)
|
var prefix, welcomeMessage string
|
||||||
go table.GetPrefix(guildId, prefix)
|
var ticketLimit uint8
|
||||||
|
var category, archiveChannel uint64
|
||||||
|
var allowUsersToClose, pingEveryone bool
|
||||||
|
var namingScheme database.NamingScheme
|
||||||
|
|
||||||
welcomeMessage := make(chan string)
|
group, _ := errgroup.WithContext(context.Background())
|
||||||
go table.GetWelcomeMessage(guildId, welcomeMessage)
|
|
||||||
|
|
||||||
ticketLimit := make(chan int)
|
// prefix
|
||||||
go table.GetTicketLimit(guildId, ticketLimit)
|
group.Go(func() (err error) {
|
||||||
|
prefix, err = dbclient.Client.Prefix.Get(guildId)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
category := make(chan uint64)
|
// welcome message
|
||||||
go table.GetChannelCategory(guildId, category)
|
group.Go(func() (err error) {
|
||||||
|
welcomeMessage, err = dbclient.Client.WelcomeMessages.Get(guildId)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
archiveChannel := make(chan uint64)
|
// ticket limit
|
||||||
go table.GetArchiveChannel(guildId, archiveChannel)
|
group.Go(func() (err error) {
|
||||||
|
ticketLimit, err = dbclient.Client.TicketLimit.Get(guildId)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
allowUsersToClose := make(chan bool)
|
// category
|
||||||
go table.IsUserCanClose(guildId, allowUsersToClose)
|
group.Go(func() (err error) {
|
||||||
|
category, err = dbclient.Client.ChannelCategory.Get(guildId)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
namingScheme := make(chan table.NamingScheme)
|
// archive channel
|
||||||
go table.GetTicketNamingScheme(guildId, namingScheme)
|
group.Go(func() (err error) {
|
||||||
|
archiveChannel, err = dbclient.Client.ArchiveChannel.Get(guildId)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
pingEveryone := make(chan bool)
|
// allow users to close
|
||||||
go table.GetPingEveryone(guildId, pingEveryone)
|
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{
|
ctx.JSON(200, Settings{
|
||||||
Prefix: <-prefix,
|
Prefix: prefix,
|
||||||
WelcomeMessaage: <-welcomeMessage,
|
WelcomeMessaage: welcomeMessage,
|
||||||
TicketLimit: <-ticketLimit,
|
TicketLimit: ticketLimit,
|
||||||
Category: <-category,
|
Category: category,
|
||||||
ArchiveChannel: <-archiveChannel,
|
ArchiveChannel: archiveChannel,
|
||||||
NamingScheme: <-namingScheme,
|
NamingScheme: namingScheme,
|
||||||
PingEveryone: <-pingEveryone,
|
PingEveryone: pingEveryone,
|
||||||
UsersCanClose: <-allowUsersToClose,
|
UsersCanClose: allowUsersToClose,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ func CreateTag(ctx *gin.Context) {
|
|||||||
return
|
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{
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ func DeleteTag(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := table.DeleteTag(guildId, tagId); err != nil {
|
if err := database.Client.Tag.Delete(guildId, tagId); err != nil {
|
||||||
ctx.JSON(500, gin.H{
|
ctx.JSON(500, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Make client take new structure
|
||||||
func TagsListHandler(ctx *gin.Context) {
|
func TagsListHandler(ctx *gin.Context) {
|
||||||
guildId := ctx.Keys["guildid"].(uint64)
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
|
|
||||||
wrapped := make([]tag, 0)
|
tags, err := database.Client.Tag.GetByGuild(guildId)
|
||||||
|
if err != nil {
|
||||||
tags := make(chan []table.Tag)
|
ctx.AbortWithStatusJSON(500, gin.H{
|
||||||
go table.GetTags(guildId, tags)
|
"success": false,
|
||||||
for _, t := range <-tags {
|
"error": err.Error(),
|
||||||
wrapped = append(wrapped, tag{
|
|
||||||
Id: t.Id,
|
|
||||||
Content: t.Content,
|
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(200, wrapped)
|
ctx.JSON(200, tags)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
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/TicketsBot/GoPanel/rpc/cache"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/objects/channel"
|
"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 {
|
func (s *Settings) updatePrefix(guildId uint64) bool {
|
||||||
if s.Prefix == "" || len(s.Prefix) > 8 {
|
if s.Prefix == "" || len(s.Prefix) > 8 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.UpdatePrefix(guildId, s.Prefix)
|
go dbclient.Client.Prefix.Set(guildId, s.Prefix)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ func (s *Settings) updateWelcomeMessage(guildId uint64) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.UpdateWelcomeMessage(guildId, s.WelcomeMessaage)
|
go dbclient.Client.WelcomeMessages.Set(guildId, s.WelcomeMessaage)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ func (s *Settings) updateTicketLimit(guildId uint64) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.UpdateTicketLimit(guildId, s.TicketLimit)
|
go dbclient.Client.TicketLimit.Set(guildId, s.TicketLimit)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ func (s *Settings) updateCategory(channels []channel.Channel, guildId uint64) bo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.UpdateChannelCategory(guildId, s.Category)
|
go dbclient.Client.ChannelCategory.Set(guildId, s.Category)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +101,11 @@ func (s *Settings) updateArchiveChannel(channels []channel.Channel, guildId uint
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.UpdateArchiveChannel(guildId, s.ArchiveChannel)
|
go dbclient.Client.ArchiveChannel.Set(guildId, s.ArchiveChannel)
|
||||||
return true
|
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 {
|
func (s *Settings) updateNamingScheme(guildId uint64) bool {
|
||||||
var valid bool
|
var valid bool
|
||||||
for _, scheme := range validScheme {
|
for _, scheme := range validScheme {
|
||||||
@ -117,14 +119,14 @@ func (s *Settings) updateNamingScheme(guildId uint64) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
go table.SetTicketNamingScheme(guildId, s.NamingScheme)
|
go dbclient.Client.NamingScheme.Set(guildId, s.NamingScheme)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Settings) updatePingEveryone(guildId uint64) {
|
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) {
|
func (s *Settings) updateUsersCanClose(guildId uint64) {
|
||||||
go table.SetUserCanClose(guildId, s.UsersCanClose)
|
go dbclient.Client.UsersCanClose.Set(guildId, s.UsersCanClose)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
"github.com/TicketsBot/archiverclient"
|
"github.com/TicketsBot/archiverclient"
|
||||||
@ -41,20 +41,27 @@ func LogViewHandler(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get ticket object
|
// get ticket object
|
||||||
ticketChan := make(chan table.Ticket)
|
ticket, err := database.Client.Tickets.Get(ticketId, guildId)
|
||||||
go table.GetTicketById(guildId, ticketId, ticketChan)
|
if err != nil {
|
||||||
ticket := <-ticketChan
|
// 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
|
// 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))
|
ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs", guild.Id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the user has permissions to be here
|
// Verify the user has permissions to be here
|
||||||
|
// TODO: Allow support reps to view
|
||||||
isAdmin := make(chan bool)
|
isAdmin := make(chan bool)
|
||||||
go utils.IsAdmin(guild, userId, isAdmin)
|
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
|
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,13 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
"github.com/TicketsBot/archiverclient"
|
"github.com/TicketsBot/archiverclient"
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gofrs/uuid"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,21 +34,35 @@ func ModmailLogViewHandler(ctx *gin.Context) {
|
|||||||
guild, _ := cache.Instance.GetGuild(guildId, false)
|
guild, _ := cache.Instance.GetGuild(guildId, false)
|
||||||
|
|
||||||
// get ticket UUID
|
// 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
|
// get ticket object
|
||||||
archiveCh := make(chan table.ModMailArchive)
|
archive, err := database.Client.ModmailArchive.Get(archiveUuid)
|
||||||
go table.GetModmailArchive(uuid, archiveCh)
|
if err != nil {
|
||||||
archive := <-archiveCh
|
// 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
|
// 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))
|
ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify this modmail ticket was for this guild
|
// 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))
|
ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -55,13 +70,13 @@ func ModmailLogViewHandler(ctx *gin.Context) {
|
|||||||
// Verify the user has permissions to be here
|
// Verify the user has permissions to be here
|
||||||
isAdmin := make(chan bool)
|
isAdmin := make(chan bool)
|
||||||
go utils.IsAdmin(guild, userId, isAdmin)
|
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
|
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve ticket messages from bucket
|
// retrieve ticket messages from bucket
|
||||||
messages, err := Archiver.GetModmail(guildId, uuid)
|
messages, err := Archiver.GetModmail(guildId, archiveUuid.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, archiverclient.ErrExpired) {
|
if errors.Is(err, archiverclient.ErrExpired) {
|
||||||
ctx.String(200, "Archives expired: Purchase premium for permanent log storage") // TODO: Actual error page
|
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
|
// 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 {
|
if err != nil {
|
||||||
ctx.String(500, fmt.Sprintf("Failed to retrieve archive - please contact the developers: %s", err.Error()))
|
ctx.String(500, fmt.Sprintf("Failed to retrieve archive - please contact the developers: %s", err.Error()))
|
||||||
return
|
return
|
||||||
|
@ -1,85 +1,19 @@
|
|||||||
package manage
|
package manage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rxdn/gdl/objects/channel"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SettingsHandler(ctx *gin.Context) {
|
func SettingsHandler(ctx *gin.Context) {
|
||||||
store := sessions.Default(ctx)
|
store := sessions.Default(ctx)
|
||||||
|
guildId := ctx.Keys["guildid"].(uint64)
|
||||||
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"
|
|
||||||
|
|
||||||
ctx.HTML(200, "manage/settings", gin.H{
|
ctx.HTML(200, "manage/settings", gin.H{
|
||||||
"name": store.Get("name").(string),
|
"name": store.Get("name").(string),
|
||||||
"guildId": guildIdStr,
|
"guildId": guildId,
|
||||||
"avatar": store.Get("avatar").(string),
|
"avatar": store.Get("avatar").(string),
|
||||||
"categories": categories,
|
"baseUrl": config.Conf.Server.BaseUrl,
|
||||||
"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),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,6 @@ func TicketViewHandler(ctx *gin.Context) {
|
|||||||
"guildId": guildId,
|
"guildId": guildId,
|
||||||
"avatar": store.Get("avatar").(string),
|
"avatar": store.Get("avatar").(string),
|
||||||
"baseUrl": config.Conf.Server.BaseUrl,
|
"baseUrl": config.Conf.Server.BaseUrl,
|
||||||
"uuid": ctx.Param("uuid"),
|
"ticketId": ctx.Param("ticketId"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package root
|
package root
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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"
|
||||||
"github.com/TicketsBot/GoPanel/utils/discord"
|
"github.com/TicketsBot/GoPanel/utils/discord"
|
||||||
userEndpoint "github.com/TicketsBot/GoPanel/utils/discord/endpoints/user"
|
userEndpoint "github.com/TicketsBot/GoPanel/utils/discord/endpoints/user"
|
||||||
|
"github.com/TicketsBot/database"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -92,6 +91,8 @@ func CallbackHandler(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wrappedGuilds []database.UserGuild
|
||||||
|
|
||||||
// endpoint's partial guild doesn't include ownerid
|
// 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
|
// 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
|
// 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 {
|
if guild.Owner {
|
||||||
guild.OwnerId = currentUser.Id
|
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)
|
// TODO: Error handling
|
||||||
if err != nil {
|
go dbclient.Client.UserGuilds.Set(currentUser.Id, wrappedGuilds)
|
||||||
log.Error(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: unfuck this
|
|
||||||
table.UpdateGuilds(currentUser.Id, base64.StdEncoding.EncodeToString(marshalled))
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package root
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
"github.com/TicketsBot/GoPanel/utils"
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -13,19 +13,31 @@ func IndexHandler(ctx *gin.Context) {
|
|||||||
store := sessions.Default(ctx)
|
store := sessions.Default(ctx)
|
||||||
userId := utils.GetUserId(store)
|
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)
|
adminGuilds := make([]guild.Guild, 0)
|
||||||
for _, g := range userGuilds {
|
for _, g := range userGuilds {
|
||||||
fakeGuild := guild.Guild{
|
fakeGuild := guild.Guild{
|
||||||
Id: g.Id,
|
Id: g.GuildId,
|
||||||
OwnerId: g.OwnerId,
|
Owner: g.Owner,
|
||||||
Permissions: g.Permissions,
|
Permissions: int(g.UserPermissions),
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Owner {
|
||||||
|
fakeGuild.OwnerId = userId
|
||||||
}
|
}
|
||||||
|
|
||||||
isAdmin := make(chan bool)
|
isAdmin := make(chan bool)
|
||||||
go utils.IsAdmin(fakeGuild, userId, isAdmin)
|
go utils.IsAdmin(fakeGuild, userId, isAdmin)
|
||||||
if <-isAdmin {
|
if <-isAdmin {
|
||||||
adminGuilds = append(adminGuilds, g)
|
adminGuilds = append(adminGuilds, fakeGuild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
@ -22,6 +21,7 @@ func AuthenticateToken(ctx *gin.Context) {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
|
"success": false,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -31,7 +31,8 @@ func AuthenticateToken(ctx *gin.Context) {
|
|||||||
userId, hasUserId := claims["userid"]
|
userId, hasUserId := claims["userid"]
|
||||||
if !hasUserId {
|
if !hasUserId {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"error": errors.New("token is invalid"),
|
"success": false,
|
||||||
|
"error": "Token is invalid",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -39,7 +40,8 @@ func AuthenticateToken(ctx *gin.Context) {
|
|||||||
parsedId, err := strconv.ParseUint(userId.(string), 10, 64)
|
parsedId, err := strconv.ParseUint(userId.(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"error": errors.New("token is invalid"),
|
"success": false,
|
||||||
|
"error": "Token is invalid",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -47,7 +49,8 @@ func AuthenticateToken(ctx *gin.Context) {
|
|||||||
ctx.Keys["userid"] = parsedId
|
ctx.Keys["userid"] = parsedId
|
||||||
} else {
|
} else {
|
||||||
ctx.AbortWithStatusJSON(403, gin.H{
|
ctx.AbortWithStatusJSON(403, gin.H{
|
||||||
"error": errors.New("token is invalid"),
|
"success": false,
|
||||||
|
"error": "Token is invalid",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,7 @@ func StartServer() {
|
|||||||
authenticateGuild.GET("/manage/:id/tags", manage.TagsHandler)
|
authenticateGuild.GET("/manage/:id/tags", manage.TagsHandler)
|
||||||
|
|
||||||
authenticateGuild.GET("/manage/:id/tickets", manage.TicketListHandler)
|
authenticateGuild.GET("/manage/:id/tickets", manage.TicketListHandler)
|
||||||
authenticateGuild.GET("/manage/:id/tickets/view/:uuid", manage.TicketViewHandler)
|
authenticateGuild.GET("/manage/:id/tickets/view/:ticketId", manage.TicketViewHandler)
|
||||||
authenticateGuild.POST("/manage/:id/tickets/view/:uuid", api.SendMessage)
|
|
||||||
|
|
||||||
authorized.GET("/webchat", manage.WebChatWs)
|
authorized.GET("/webchat", manage.WebChatWs)
|
||||||
}
|
}
|
||||||
@ -90,13 +89,13 @@ func StartServer() {
|
|||||||
guildAuthApi.PUT("/:id/panels", api.CreatePanel)
|
guildAuthApi.PUT("/:id/panels", api.CreatePanel)
|
||||||
guildAuthApi.DELETE("/:id/panels/:message", api.DeletePanel)
|
guildAuthApi.DELETE("/:id/panels/:message", api.DeletePanel)
|
||||||
|
|
||||||
guildAuthApi.GET("/:id/logs/:page", api.GetLogs)
|
guildAuthApi.GET("/:id/logs/", api.GetLogs)
|
||||||
guildAuthApi.GET("/:id/modmail/logs/:page", api.GetModmailLogs)
|
guildAuthApi.GET("/:id/modmail/logs/", api.GetModmailLogs)
|
||||||
|
|
||||||
guildAuthApi.GET("/:id/tickets", api.GetTickets)
|
guildAuthApi.GET("/:id/tickets", api.GetTickets)
|
||||||
guildAuthApi.GET("/:id/tickets/:uuid", api.GetTicket)
|
guildAuthApi.GET("/:id/tickets/:ticketId", api.GetTicket)
|
||||||
guildAuthApi.POST("/:id/tickets/:uuid", api.SendMessage)
|
guildAuthApi.POST("/:id/tickets/:ticketId", api.SendMessage)
|
||||||
guildAuthApi.DELETE("/:id/tickets/:uuid", api.CloseTicket)
|
guildAuthApi.DELETE("/:id/tickets/:ticketId", api.CloseTicket)
|
||||||
|
|
||||||
guildAuthApi.GET("/:id/tags", api.TagsListHandler)
|
guildAuthApi.GET("/:id/tags", api.TagsListHandler)
|
||||||
guildAuthApi.PUT("/:id/tags", api.CreateTag)
|
guildAuthApi.PUT("/:id/tags", api.CreateTag)
|
||||||
|
@ -16,12 +16,8 @@ id=
|
|||||||
secret=""
|
secret=""
|
||||||
redirectUri=""
|
redirectUri=""
|
||||||
|
|
||||||
[mariadb]
|
[database]
|
||||||
host="127.0.0.1"
|
uri="postgres://user:pwd@localhost:5432/database?pool_max_conns=10"
|
||||||
username="ryan"
|
|
||||||
password="ryan"
|
|
||||||
database="tickets"
|
|
||||||
threads=5
|
|
||||||
|
|
||||||
[bot]
|
[bot]
|
||||||
token=""
|
token=""
|
||||||
|
@ -10,7 +10,7 @@ type (
|
|||||||
Admins []string
|
Admins []string
|
||||||
Server Server
|
Server Server
|
||||||
Oauth Oauth
|
Oauth Oauth
|
||||||
MariaDB MariaDB
|
Database Database
|
||||||
Bot Bot
|
Bot Bot
|
||||||
Redis Redis
|
Redis Redis
|
||||||
Cache Cache
|
Cache Cache
|
||||||
@ -41,12 +41,8 @@ type (
|
|||||||
RedirectUri string
|
RedirectUri string
|
||||||
}
|
}
|
||||||
|
|
||||||
MariaDB struct {
|
Database struct {
|
||||||
Host string
|
Uri string
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
Database string
|
|
||||||
Threads int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot struct {
|
Bot struct {
|
||||||
|
@ -1,35 +1,31 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
"github.com/TicketsBot/database"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jackc/pgx/v4"
|
||||||
|
"github.com/jackc/pgx/v4/log/logrusadapter"
|
||||||
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var Client *database.Database
|
||||||
Database gorm.DB
|
|
||||||
)
|
|
||||||
|
|
||||||
func ConnectToDatabase() {
|
func ConnectToDatabase() {
|
||||||
uri := fmt.Sprintf(
|
config, err := pgxpool.ParseConfig(config.Conf.Database.Uri); if err != nil {
|
||||||
"%s:%s@tcp(%s:3306)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
panic(err)
|
||||||
config.Conf.MariaDB.Username,
|
}
|
||||||
config.Conf.MariaDB.Password,
|
|
||||||
config.Conf.MariaDB.Host,
|
|
||||||
config.Conf.MariaDB.Database,
|
|
||||||
)
|
|
||||||
|
|
||||||
db, err := gorm.Open("mysql", uri)
|
// TODO: Sentry
|
||||||
|
config.ConnConfig.LogLevel = pgx.LogLevelWarn
|
||||||
|
config.ConnConfig.Logger = logrusadapter.NewLogger(logrus.New())
|
||||||
|
|
||||||
|
pool, err := pgxpool.ConnectConfig(context.Background(), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.DB().SetMaxOpenConns(config.Conf.MariaDB.Threads)
|
Client = database.NewDatabase(pool)
|
||||||
db.DB().SetMaxIdleConns(0)
|
Client.CreateTables(pool)
|
||||||
|
|
||||||
db.Set("gorm:table_options", "charset=utf8mb4")
|
|
||||||
db.BlockGlobalUpdate(true)
|
|
||||||
|
|
||||||
Database = *db
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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{})
|
|
||||||
}
|
|
@ -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{})
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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, ",")
|
|
||||||
}
|
|
@ -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,
|
|
||||||
})
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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{})
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
5
go.mod
5
go.mod
@ -5,6 +5,7 @@ go 1.14
|
|||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/TicketsBot/archiverclient v0.0.0-20200425115930-0ca198cc8306
|
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/apex/log v1.1.2
|
||||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
|
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
@ -14,6 +15,7 @@ require (
|
|||||||
github.com/gin-gonic/gin v1.6.2
|
github.com/gin-gonic/gin v1.6.2
|
||||||
github.com/go-redis/redis v6.15.7+incompatible
|
github.com/go-redis/redis v6.15.7+incompatible
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
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/sessions v1.2.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/jackc/pgx/v4 v4.6.0
|
github.com/jackc/pgx/v4 v4.6.0
|
||||||
@ -21,8 +23,9 @@ require (
|
|||||||
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c
|
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62
|
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/satori/go.uuid v1.2.0
|
||||||
|
github.com/sirupsen/logrus v1.5.0
|
||||||
github.com/ulule/limiter/v3 v3.5.0
|
github.com/ulule/limiter/v3 v3.5.0
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||||
)
|
)
|
||||||
|
@ -2,11 +2,11 @@ package messagequeue
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
"github.com/TicketsBot/database"
|
||||||
"github.com/apex/log"
|
"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 {
|
encoded, err := json.Marshal(settings); if err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -6,23 +6,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TicketCloseMessage struct {
|
type TicketCloseMessage struct {
|
||||||
Uuid string
|
GuildId uint64
|
||||||
|
TicketId int
|
||||||
User uint64
|
User uint64
|
||||||
Reason string
|
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{
|
settings := TicketCloseMessage{
|
||||||
Uuid: ticket,
|
GuildId: guildId,
|
||||||
|
TicketId: ticketId,
|
||||||
User: userId,
|
User: userId,
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
}
|
}
|
||||||
|
|
||||||
encoded, err := json.Marshal(settings); if err != nil {
|
encoded, err := json.Marshal(settings)
|
||||||
|
if err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Publish("tickets:close", string(encoded))
|
c.Publish("tickets:close", string(encoded))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,13 +84,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--<div aria-live="polite" aria-atomic="true" style="position: relative">
|
<div aria-live="polite" aria-atomic="true" style="position: relative">
|
||||||
<div style="position: absolute; right: 10px" id="toast-container">
|
<div style="position: absolute; right: 10px" id="toast-container">
|
||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// TODO: Implement before param
|
||||||
|
const pageLimit = 30;
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
|
let logs = [];
|
||||||
|
|
||||||
function appendLog(log) {
|
function appendLog(log) {
|
||||||
const container = document.getElementById('log-container');
|
const container = document.getElementById('log-container');
|
||||||
@ -105,30 +108,35 @@
|
|||||||
container.appendChild(tr);
|
container.appendChild(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadPage(page, ticketId, username, userId) {
|
async function loadData(before, ticketId, username, userId) {
|
||||||
|
if (before === undefined) {
|
||||||
|
before = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const container = document.getElementById('log-container');
|
const container = document.getElementById('log-container');
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
||||||
let url = '/api/{{.guildId}}/logs/' + page;
|
let url = '/api/{{.guildId}}/logs?before=' + before;
|
||||||
|
|
||||||
if (ticketId !== undefined) {
|
if (ticketId !== undefined) {
|
||||||
url += `?ticketid=${ticketId}`;
|
url += `&ticketid=${ticketId}`;
|
||||||
} else if (username !== undefined) {
|
} else if (username !== undefined) {
|
||||||
url += `?username=${username}`;
|
url += `&username=${username}`;
|
||||||
} else if (userId !== undefined) {
|
} else if (userId !== undefined) {
|
||||||
url += `?userid=${userId}`;
|
url += `&userid=${userId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await axios.get(url);
|
const res = await axios.get(url);
|
||||||
|
if (res.status === 200) {
|
||||||
|
logs = res.data;
|
||||||
for (log of res.data) {
|
for (log of res.data) {
|
||||||
appendLog(log);
|
appendLog(log);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
document.getElementById('page-number').innerText = page;
|
showToast('Error', res.data.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadData() {
|
document.getElementById('page-number').innerText = currentPage;
|
||||||
await loadPage(currentPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData();
|
loadData();
|
||||||
@ -136,8 +144,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
async function next() {
|
async function next() {
|
||||||
|
if (logs.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
currentPage += 1;
|
currentPage += 1;
|
||||||
await loadPage(currentPage);
|
await loadData(logs[logs.length - 1].ticketid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function previous() {
|
async function previous() {
|
||||||
@ -145,8 +157,13 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let before = pageLimit;
|
||||||
|
if (logs.length > 0) {
|
||||||
|
before = logs[0] + pageLimit;
|
||||||
|
}
|
||||||
|
|
||||||
currentPage -= 1;
|
currentPage -= 1;
|
||||||
await loadPage(currentPage);
|
await loadData(before);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function filterLogs() {
|
async function filterLogs() {
|
||||||
@ -155,13 +172,13 @@
|
|||||||
const userId = document.getElementById('userid').value;
|
const userId = document.getElementById('userid').value;
|
||||||
|
|
||||||
if (ticketId > 0) {
|
if (ticketId > 0) {
|
||||||
await loadPage(1, ticketId);
|
await loadData(0, ticketId);
|
||||||
} else if (username !== "") {
|
} else if (username !== "") {
|
||||||
await loadPage(1, undefined, username);
|
await loadData(0, undefined, username);
|
||||||
} else if (userId !== "") {
|
} else if (userId !== "") {
|
||||||
await loadPage(1, undefined, undefined, userId);
|
await loadData(0, undefined, undefined, userId);
|
||||||
} else {
|
} else {
|
||||||
await loadPage(1);
|
await loadData(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
|
let archives = [];
|
||||||
|
|
||||||
async function getUsername(userId) {
|
async function getUsername(userId) {
|
||||||
const res = await axios.get('/api/{{.guildId}}/user/' + userId);
|
const res = await axios.get('/api/{{.guildId}}/user/' + userId);
|
||||||
@ -103,41 +104,57 @@
|
|||||||
container.appendChild(tr);
|
container.appendChild(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadPage(page, ticketId, username, userId) {
|
async function loadData(after, before, username, userId) {
|
||||||
const container = document.getElementById('log-container');
|
if (after === undefined) after = '';
|
||||||
container.innerHTML = '';
|
if (before === undefined) before = '';
|
||||||
|
|
||||||
let url = '/api/{{.guildId}}/modmail/logs/' + page;
|
let url = '/api/{{.guildId}}/modmail/logs?after=' + after + '&before=' + before;
|
||||||
|
|
||||||
if (username !== undefined) {
|
if (username !== undefined) {
|
||||||
url += `?username=${username}`;
|
url += `&username=${username}`;
|
||||||
} else if (userId !== undefined) {
|
} else if (userId !== undefined) {
|
||||||
url += `?userid=${userId}`;
|
url += `&userid=${userId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await axios.get(url);
|
const res = await axios.get(url);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
if (res.data.length === 0 && username === "" && userId === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = document.getElementById('log-container');
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
archives = res.data;
|
||||||
|
|
||||||
for (log of res.data) {
|
for (log of res.data) {
|
||||||
await appendLog(log);
|
await appendLog(log);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showToast('Error', res.data.error);
|
showToast('Error', res.data.error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('page-number').innerText = page;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
async function loadData() {
|
|
||||||
await loadPage(currentPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData();
|
loadData();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
function updatePageNumber() {
|
||||||
|
document.getElementById('page-number').innerText = currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
async function next() {
|
async function next() {
|
||||||
|
if (archives.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await loadData(undefined, archives[archives.length - 1].uuid)) {
|
||||||
currentPage += 1;
|
currentPage += 1;
|
||||||
await loadPage(currentPage);
|
updatePageNumber();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function previous() {
|
async function previous() {
|
||||||
@ -145,21 +162,32 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPage -= 1;
|
let after = '';
|
||||||
await loadPage(currentPage);
|
if (archives.length > 0) {
|
||||||
|
after = archives[0].uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (await loadData(after)) {
|
||||||
|
currentPage -= 1;
|
||||||
|
updatePageNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Paginate filtered logs
|
||||||
async function filterLogs() {
|
async function filterLogs() {
|
||||||
const username = document.getElementById('username').value;
|
const username = document.getElementById('username').value;
|
||||||
const userId = document.getElementById('userid').value;
|
const userId = document.getElementById('userid').value;
|
||||||
|
|
||||||
if (username !== "") {
|
if (username !== "") {
|
||||||
await loadPage(1, undefined, username);
|
await loadData(undefined, undefined, username);
|
||||||
} else if (userId !== "") {
|
} else if (userId !== "") {
|
||||||
await loadPage(1, undefined, undefined, userId);
|
await loadData(undefined, undefined, undefined, userId);
|
||||||
} else {
|
} else {
|
||||||
await loadPage(1);
|
await loadData(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentPage = 1;
|
||||||
|
updatePageNumber();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
@ -155,6 +155,7 @@
|
|||||||
|
|
||||||
const res = await axios.put('/api/{{.guildId}}/panels', data);
|
const res = await axios.put('/api/{{.guildId}}/panels', data);
|
||||||
if (res.status === 200 && res.data.success) {
|
if (res.status === 200 && res.data.success) {
|
||||||
|
data.message_id = res.data.message_id;
|
||||||
appendPanel(data, await getChannels());
|
appendPanel(data, await getChannels());
|
||||||
showToast('Success', 'Panel created successfully')
|
showToast('Success', 'Panel created successfully')
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label>Welcome Message (Max len. 1000)</label>
|
<label>Welcome Message (Max len. 1000)</label>
|
||||||
<textarea name="welcomeMessage" class="form-control" rows="3" id="welcome_message"
|
<textarea name="welcomeMessage" class="form-control" rows="3" id="welcome_message"
|
||||||
style="resize: none">{{.welcomeMessage}}</textarea>
|
style="resize: none"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
const res = await axios.put('/api/{{.guildId}}/tags', data);
|
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('id').value = '';
|
||||||
document.getElementById('content').value = '';
|
document.getElementById('content').value = '';
|
||||||
|
|
||||||
@ -96,14 +96,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function appendTag(tag) {
|
function appendTag(id, content) {
|
||||||
const container = document.getElementById('tag-container');
|
const container = document.getElementById('tag-container');
|
||||||
const tr = document.createElement('tr');
|
const tr = document.createElement('tr');
|
||||||
tr.id = tag.id;
|
tr.id = id;
|
||||||
|
|
||||||
appendTd(tr, tag.id);
|
appendTd(tr, id);
|
||||||
appendTd(tr, tag.content).classList.add('tag-content');
|
appendTd(tr, content).classList.add('tag-content');
|
||||||
appendButton(tr, 'Delete', () => { deleteTag(tag.id); });
|
appendButton(tr, 'Delete', () => { deleteTag(id); });
|
||||||
|
|
||||||
container.appendChild(tr);
|
container.appendChild(tr);
|
||||||
}
|
}
|
||||||
@ -112,8 +112,8 @@
|
|||||||
const res = await axios.get('/api/{{.guildId}}/tags');
|
const res = await axios.get('/api/{{.guildId}}/tags');
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
for (tag of res.data) {
|
for (const [id, content] of Object.entries(res.data)) {
|
||||||
appendTag(tag);
|
appendTag(id, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
const members = ticket.members.map(member => `${member.username}#${member.discrim}`).join(', ');
|
const members = ticket.members.map(member => `${member.username}#${member.discrim}`).join(', ');
|
||||||
appendTd(tr, members);
|
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);
|
container.appendChild(tr);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
const reason = document.getElementById('reason').value;
|
const reason = document.getElementById('reason').value;
|
||||||
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: {
|
data: {
|
||||||
reason: reason
|
reason: reason
|
||||||
}
|
}
|
||||||
@ -86,20 +86,20 @@
|
|||||||
async function loadData() {
|
async function loadData() {
|
||||||
const premium = await isPremium();
|
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) {
|
if (res.status === 200 && res.data.success) {
|
||||||
const data = res.data;
|
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);
|
await appendMessages(data.messages);
|
||||||
|
|
||||||
startWebsocket(data.ticket.TicketId);
|
startWebsocket(data.ticket.Id);
|
||||||
} else {
|
} else {
|
||||||
showToast('Error', res.data.error);
|
showToast('Error', res.data.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const el = document.getElementById('message');
|
const el = document.getElementById('message');
|
||||||
if (premium) {
|
if (premium) {
|
||||||
el.placeholder = `Message #ticket-${res.data.ticket.TicketId}`;
|
el.placeholder = `Message #ticket-${res.data.ticket.Id}`;
|
||||||
} else {
|
} else {
|
||||||
el.disabled = true;
|
el.disabled = true;
|
||||||
el.placeholder = 'Premium users get live messages and can respond through webchat'
|
el.placeholder = 'Premium users get live messages and can respond through webchat'
|
||||||
@ -115,7 +115,8 @@
|
|||||||
container.scrollTop = container.scrollHeight;
|
container.scrollTop = container.scrollHeight;
|
||||||
|
|
||||||
async function startWebsocket(ticketId) {
|
async function startWebsocket(ticketId) {
|
||||||
const ws = new WebSocket("wss://panel.ticketsbot.net/webchat");
|
//const ws = new WebSocket("wss://panel.ticketsbot.net/webchat");
|
||||||
|
const ws = new WebSocket("ws://localhost:3000/webchat");
|
||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
@ -138,7 +139,7 @@
|
|||||||
const msg = document.getElementById("message").value;
|
const msg = document.getElementById("message").value;
|
||||||
document.getElementById("message").value = "";
|
document.getElementById("message").value = "";
|
||||||
|
|
||||||
const res = await axios.post('/api/{{.guildId}}/tickets/{{.uuid}}', {message: msg});
|
const res = await axios.post('/api/{{.guildId}}/tickets/{{.ticketId}}', {message: msg});
|
||||||
if (res.status !== 200 || !res.data.success) {
|
if (res.status !== 200 || !res.data.success) {
|
||||||
showToast('Error', res.data.error);
|
showToast('Error', res.data.error);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"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/cache"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
"github.com/apex/log"
|
"github.com/apex/log"
|
||||||
@ -16,17 +16,22 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Use Redis cache
|
||||||
|
// TODO: Error handling
|
||||||
func IsAdmin(g guild.Guild, userId uint64, res chan bool) {
|
func IsAdmin(g guild.Guild, userId uint64, res chan bool) {
|
||||||
if Contains(config.Conf.Admins, strconv.Itoa(int(userId))) {
|
if Contains(config.Conf.Admins, strconv.FormatUint(userId, 10)) {
|
||||||
res <- true
|
res <- true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.OwnerId == userId {
|
if g.OwnerId == userId {
|
||||||
res <- true
|
res <- true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if table.IsAdmin(g.Id, userId) {
|
if isAdmin, _ := database.Client.Permissions.IsAdmin(g.Id, userId); isAdmin {
|
||||||
res <- true
|
res <- true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userRoles, _ := getRoles(g.Id, userId)
|
userRoles, _ := getRoles(g.Id, userId)
|
||||||
@ -34,11 +39,10 @@ func IsAdmin(g guild.Guild, userId uint64, res chan bool) {
|
|||||||
// check if user has administrator permission
|
// check if user has administrator permission
|
||||||
if hasAdministratorPermission(g.Id, userRoles) {
|
if hasAdministratorPermission(g.Id, userRoles) {
|
||||||
res <- true
|
res <- true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
adminRolesChan := make(chan []uint64)
|
adminRoles, _ := database.Client.RolePermissions.GetAdminRoles(g.Id)
|
||||||
go table.GetAdminRoles(g.Id, adminRolesChan)
|
|
||||||
adminRoles := <-adminRolesChan
|
|
||||||
|
|
||||||
hasTicketAdminRole := false
|
hasTicketAdminRole := false
|
||||||
for _, userRole := range userRoles {
|
for _, userRole := range userRoles {
|
||||||
@ -52,6 +56,7 @@ func IsAdmin(g guild.Guild, userId uint64, res chan bool) {
|
|||||||
|
|
||||||
if hasTicketAdminRole {
|
if hasTicketAdminRole {
|
||||||
res <- true
|
res <- true
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res <- false
|
res <- false
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TicketsBot/GoPanel/config"
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
"github.com/TicketsBot/GoPanel/database/table"
|
|
||||||
"github.com/TicketsBot/GoPanel/rpc/cache"
|
"github.com/TicketsBot/GoPanel/rpc/cache"
|
||||||
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
"github.com/TicketsBot/GoPanel/rpc/ratelimit"
|
||||||
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
gocache "github.com/robfig/go-cache"
|
gocache "github.com/robfig/go-cache"
|
||||||
"github.com/rxdn/gdl/rest"
|
"github.com/rxdn/gdl/rest"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -20,6 +20,7 @@ type ProxyResponse struct {
|
|||||||
Tier int
|
Tier int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Use Redis cache
|
||||||
var premiumCache = gocache.New(10 * time.Minute, 10 * time.Minute)
|
var premiumCache = gocache.New(10 * time.Minute, 10 * time.Minute)
|
||||||
|
|
||||||
func IsPremiumGuild(guildId uint64, ch chan bool) {
|
func IsPremiumGuild(guildId uint64, ch chan bool) {
|
||||||
@ -31,10 +32,11 @@ func IsPremiumGuild(guildId uint64, ch chan bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First lookup by premium key, then votes, then patreon
|
// First lookup by premium key, then votes, then patreon
|
||||||
keyLookup := make(chan bool)
|
// TODO: Lookup Patreon first
|
||||||
go table.IsPremium(guildId, keyLookup)
|
// TODO: Handle error
|
||||||
|
hasPremiumKey, _ := database.Client.PremiumGuilds.IsPremium(guildId)
|
||||||
|
|
||||||
if <-keyLookup {
|
if hasPremiumKey {
|
||||||
if err := premiumCache.Add(guildIdRaw, true, 10 * time.Minute); err != nil {
|
if err := premiumCache.Add(guildIdRaw, true, 10 * time.Minute); err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user