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