Use batch create slash command endpoint

This commit is contained in:
rxdn 2021-02-09 20:49:44 +00:00
parent 6606f7a3bf
commit e0ceebc02e
11 changed files with 19 additions and 355 deletions

View File

@ -1,87 +0,0 @@
package api
import (
"context"
"fmt"
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"
)
var modmailPathRegex = regexp.MustCompile(`(\d+)\/modmail\/(?:free-)?([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})`)
type wrappedModLog struct {
Uuid string `json:"uuid"`
GuildId uint64 `json:"guild_id,string"`
UserId uint64 `json:"user_id,string"`
}
// TODO: Take after param
func GetModmailLogs(ctx *gin.Context) {
guildId := ctx.Keys["guildid"].(uint64)
after, err := uuid.FromString(ctx.Query("after"))
if err != nil {
after = uuid.Nil
}
before, err := uuid.FromString(ctx.Query("before"))
if err != nil {
before = uuid.Nil
}
// filter
var userId uint64
if userIdRaw, filterByUserId := ctx.GetQuery("userid"); filterByUserId {
userId, err = strconv.ParseUint(userIdRaw, 10, 64)
if err != nil {
ctx.AbortWithStatusJSON(400, gin.H{
"success": false,
"error": "Invalid user ID",
})
return
}
} else if username, filterByUsername := ctx.GetQuery("username"); filterByUsername {
if err := cache.Instance.QueryRow(context.Background(), `select users.user_id from users where LOWER("data"->>'Username') LIKE LOWER($1) and exists(SELECT FROM members where members.guild_id=$2);`, fmt.Sprintf("%%%s%%", username), guildId).Scan(&userId); err != nil {
ctx.AbortWithStatusJSON(404, gin.H{
"success": false,
"error": "User not found",
})
return
}
}
shouldFilter := userId > 0
wrapped := make([]wrappedModLog, 0)
var archives []database.ModmailArchive
if shouldFilter {
archives, err = dbclient.Client.ModmailArchive.GetByMember(guildId, userId, pageLimit, after, before)
} else {
archives, err = dbclient.Client.ModmailArchive.GetByGuild(guildId, pageLimit, after, before)
}
if err != nil {
ctx.AbortWithStatusJSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
for _, archive := range archives {
wrapped = append(wrapped, wrappedModLog{
Uuid: archive.Uuid.String(),
GuildId: archive.GuildId,
UserId: archive.UserId,
})
}
ctx.JSON(200, wrapped)
}

View File

@ -18,7 +18,6 @@ type Settings struct {
PingEveryone bool `json:"ping_everyone"` PingEveryone bool `json:"ping_everyone"`
UsersCanClose bool `json:"users_can_close"` UsersCanClose bool `json:"users_can_close"`
CloseConfirmation bool `json:"close_confirmation"` CloseConfirmation bool `json:"close_confirmation"`
ModmailEnabled bool `json:"modmail_enabled"`
} }
func GetSettingsHandler(ctx *gin.Context) { func GetSettingsHandler(ctx *gin.Context) {
@ -82,12 +81,6 @@ func GetSettingsHandler(ctx *gin.Context) {
return return
}) })
// modmail enabled
group.Go(func() (err error) {
settings.ModmailEnabled, err = dbclient.Client.ModmailEnabled.Get(guildId)
return
})
if err := group.Wait(); err != nil { if err := group.Wait(); err != nil {
ctx.AbortWithStatusJSON(500, gin.H{ ctx.AbortWithStatusJSON(500, gin.H{
"success": false, "success": false,

View File

@ -33,7 +33,6 @@ func UpdateSettingsHandler(ctx *gin.Context) {
settings.updatePingEveryone(guildId) settings.updatePingEveryone(guildId)
settings.updateUsersCanClose(guildId) settings.updateUsersCanClose(guildId)
settings.updateCloseConfirmation(guildId) settings.updateCloseConfirmation(guildId)
settings.updateModmailEnabled(guildId)
ctx.JSON(200, gin.H{ ctx.JSON(200, gin.H{
"prefix": validPrefix, "prefix": validPrefix,
@ -136,7 +135,3 @@ func (s *Settings) updateUsersCanClose(guildId uint64) {
func (s *Settings) updateCloseConfirmation(guildId uint64) { func (s *Settings) updateCloseConfirmation(guildId uint64) {
go dbclient.Client.CloseConfirmation.Set(guildId, s.CloseConfirmation) go dbclient.Client.CloseConfirmation.Set(guildId, s.CloseConfirmation)
} }
func (s *Settings) updateModmailEnabled(guildId uint64) {
go dbclient.Client.ModmailEnabled.Set(guildId, s.ModmailEnabled)
}

View File

@ -37,7 +37,7 @@ func WhitelabelCreateInteractions(ctx *gin.Context) {
key := fmt.Sprintf("tickets:interaction-create-cooldown:%d", bot.BotId) key := fmt.Sprintf("tickets:interaction-create-cooldown:%d", bot.BotId)
// try to set first, prevent race condition // try to set first, prevent race condition
wasSet, err := messagequeue.Client.SetNX(key, 1, time.Minute * 15).Result() wasSet, err := messagequeue.Client.SetNX(key, 1, time.Minute).Result()
if err != nil { if err != nil {
ctx.JSON(500, gin.H{ ctx.JSON(500, gin.H{
"success": false, "success": false,
@ -59,7 +59,7 @@ func WhitelabelCreateInteractions(ctx *gin.Context) {
ctx.JSON(400, gin.H{ ctx.JSON(400, gin.H{
"success": false, "success": false,
"error": fmt.Sprintf("Interaction creation on cooldown, please wait another %d minutes", int64(expiration.Minutes())), "error": fmt.Sprintf("Interaction creation on cooldown, please wait another %d seconds", int64(expiration.Seconds())),
}) })
return return
@ -74,6 +74,7 @@ func WhitelabelCreateInteractions(ctx *gin.Context) {
return return
} }
var interactions []rest.CreateCommandData
for _, cmd := range command.Commands { for _, cmd := range command.Commands {
properties := cmd.Properties() properties := cmd.Properties()
@ -89,18 +90,17 @@ func WhitelabelCreateInteractions(ctx *gin.Context) {
Options: option.Options, Options: option.Options,
} }
if _, err := rest.CreateGlobalCommand(bot.Token, botContext.RateLimiter, bot.BotId, data); err != nil { interactions = append(interactions, data)
}
if _, err = rest.ModifyGlobalCommands(bot.Token, botContext.RateLimiter, bot.BotId, interactions); err == nil {
ctx.JSON(200, gin.H{
"success": true,
})
} else {
ctx.JSON(500, gin.H{ ctx.JSON(500, gin.H{
"success": false, "success": false,
"error": err.Error(), "error": err.Error(),
}) })
return
} }
time.Sleep(time.Second)
}
ctx.JSON(200, gin.H{
"success": true,
})
} }

View File

@ -35,21 +35,10 @@ func WhitelabelGet(ctx *gin.Context) {
return return
} }
// Get forced modmail guild
forcedGuild, err := database.Client.ModmailForcedGuilds.Get(bot.BotId)
if err != nil {
ctx.JSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
ctx.JSON(200, gin.H{ ctx.JSON(200, gin.H{
"success": true, "success": true,
"id": strconv.FormatUint(bot.BotId, 10), "id": strconv.FormatUint(bot.BotId, 10),
"status": status, "status": status,
"modmail_forced_guild": strconv.FormatUint(forcedGuild, 10),
}) })
} }
} }

View File

@ -1,110 +0,0 @@
package api
import (
"github.com/TicketsBot/GoPanel/database"
"github.com/gin-gonic/gin"
"strconv"
)
func WhitelabelModmailPost(ctx *gin.Context) {
userId := ctx.Keys["userid"].(uint64)
// Get bot
bot, err := database.Client.Whitelabel.GetByUserId(userId)
if err != nil {
ctx.JSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
// Ensure bot exists
if bot.BotId == 0 {
ctx.JSON(404, gin.H{
"success": false,
"error": "No bot found",
})
return
}
// Parse status
var guildId uint64
{
var data map[string]string
if err := ctx.BindJSON(&data); err != nil {
ctx.JSON(400, gin.H{
"success": false,
"error": "No guild ID provided",
})
return
}
guildIdStr, ok := data["guild"]
if !ok {
ctx.JSON(400, gin.H{
"success": false,
"error": "No guild ID provided",
})
return
}
guildId, err = strconv.ParseUint(guildIdStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{
"success": false,
"error": "Invalid guild ID provided",
})
return
}
}
if guildId == 0 {
if err := database.Client.ModmailForcedGuilds.Delete(bot.BotId); err != nil {
ctx.JSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
}
// verify that the bot is in the specified guild
guilds, err := database.Client.WhitelabelGuilds.GetGuilds(bot.BotId)
if err != nil {
ctx.JSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
var found bool
for _, botGuild := range guilds {
if botGuild == guildId {
found = true
break
}
}
if !found {
ctx.JSON(400, gin.H{
"success": false,
"error": "The bot isn't in the guild your provided",
})
return
}
if err := database.Client.ModmailForcedGuilds.Set(bot.BotId, guildId); err != nil {
ctx.JSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return
}
ctx.JSON(200, gin.H{
"success": true,
"bot": bot,
})
}

View File

@ -1,19 +0,0 @@
package manage
import (
"github.com/TicketsBot/GoPanel/config"
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
)
func ModmailLogsHandler(ctx *gin.Context) {
store := sessions.Default(ctx)
guildId := ctx.Keys["guildid"].(uint64)
ctx.HTML(200, "manage/modmaillogs", gin.H{
"name": store.Get("name").(string),
"guildId": guildId,
"avatar": store.Get("avatar").(string),
"baseUrl": config.Conf.Server.BaseUrl,
})
}

View File

@ -1,93 +0,0 @@
package manage
import (
"errors"
"fmt"
"github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/archiverclient"
"github.com/TicketsBot/common/permission"
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"strconv"
)
func ModmailLogViewHandler(ctx *gin.Context) {
store := sessions.Default(ctx)
if store == nil {
return
}
if utils.IsLoggedIn(store) {
userId := utils.GetUserId(store)
// Verify the guild exists
guildId, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
utils.ErrorPage(ctx, 404, "Couldn't find a server with the ID provided")
return
}
// get ticket UUID
archiveUuid, err := uuid.FromString(ctx.Param("uuid"))
if err != nil {
utils.ErrorPage(ctx, 404, "Modmail archive with provided UUID not found")
return
}
// get ticket object
archive, err := database.Client.ModmailArchive.Get(archiveUuid)
if err != nil {
utils.ErrorPage(ctx, 500, err.Error())
return
}
// Verify this is a valid ticket and it is closed
if archive.Uuid == uuid.Nil {
utils.ErrorPage(ctx, 404, "Modmail archive with provided UUID not found")
return
}
// Verify this modmail ticket was for this guild
if archive.GuildId != guildId {
utils.ErrorPage(ctx, 403, "Modmail archive does not belong to this server")
return
}
// Verify the user has permissions to be here
permLevel, err := utils.GetPermissionLevel(guildId, userId)
if err != nil {
ctx.JSON(500, utils.ErrorToResponse(err))
return
}
if permLevel < permission.Support && archive.UserId != userId {
utils.ErrorPage(ctx, 403, "You do not have permission to view this archive")
return
}
// retrieve ticket messages from bucket
messages, err := Archiver.GetModmail(guildId, archiveUuid.String())
if err != nil {
if errors.Is(err, archiverclient.ErrExpired) {
utils.ErrorPage(ctx, 404, "Archive expired - purchase premium for permanent log storage")
} else {
utils.ErrorPage(ctx, 500, err.Error())
}
return
}
// format to html
html, err := Archiver.Encode(messages, fmt.Sprintf("modmail-%s", archiveUuid))
if err != nil {
utils.ErrorPage(ctx, 500, err.Error())
return
}
ctx.Data(200, gin.MIMEHTML, html)
} else {
ctx.Redirect(302, fmt.Sprintf("/login?noguilds&state=viewlog.%s.%s", ctx.Param("id"), ctx.Param("ticket")))
}
}

View File

@ -107,7 +107,6 @@ func StartServer() {
guildAuthApiAdmin.DELETE("/multipanels/:panelid", api_panels.MultiPanelDelete) guildAuthApiAdmin.DELETE("/multipanels/:panelid", api_panels.MultiPanelDelete)
guildAuthApiSupport.GET("/logs/", api_logs.GetLogs) guildAuthApiSupport.GET("/logs/", api_logs.GetLogs)
guildAuthApiSupport.GET("/modmail/logs/", api_logs.GetModmailLogs)
guildAuthApiSupport.GET("/tickets", api_ticket.GetTickets) guildAuthApiSupport.GET("/tickets", api_ticket.GetTickets)
guildAuthApiSupport.GET("/tickets/:ticketId", api_ticket.GetTicket) guildAuthApiSupport.GET("/tickets/:ticketId", api_ticket.GetTicket)

9
go.mod
View File

@ -5,9 +5,9 @@ go 1.14
require ( require (
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/TicketsBot/archiverclient v0.0.0-20200704164621-09d42dd941e0 github.com/TicketsBot/archiverclient v0.0.0-20200704164621-09d42dd941e0
github.com/TicketsBot/common v0.0.0-20210118171457-d5362b26aa6f github.com/TicketsBot/common v0.0.0-20210118172556-0b20b84f7df4
github.com/TicketsBot/database v0.0.0-20201224193659-c89391f44b57 github.com/TicketsBot/database v0.0.0-20210106171550-992a749cd82a
github.com/TicketsBot/worker v0.0.0-20201224203453-0c8f9a415306 github.com/TicketsBot/worker v0.0.0-20210207182653-fabef254ea30
github.com/apex/log v1.1.2 github.com/apex/log v1.1.2
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
@ -16,13 +16,12 @@ require (
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607
github.com/gin-gonic/gin v1.6.2 github.com/gin-gonic/gin v1.6.2
github.com/go-redis/redis v6.15.9+incompatible github.com/go-redis/redis v6.15.9+incompatible
github.com/gofrs/uuid v3.3.0+incompatible
github.com/gorilla/sessions v1.2.0 // indirect github.com/gorilla/sessions v1.2.0 // indirect
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/jackc/pgx/v4 v4.7.1 github.com/jackc/pgx/v4 v4.7.1
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rxdn/gdl v0.0.0-20210105220812-1d2789cb2f0b github.com/rxdn/gdl v0.0.0-20210209203918-0eb7209c47db
github.com/sirupsen/logrus v1.5.0 github.com/sirupsen/logrus v1.5.0
github.com/ulule/limiter/v3 v3.5.0 github.com/ulule/limiter/v3 v3.5.0
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a

View File

@ -280,10 +280,8 @@
} }
async function createSlashCommands() { async function createSlashCommands() {
notify('Slash Commands', 'Creating slash commands, please note this may take up to 120 seconds to complete');
const opts = { const opts = {
timeout: 120 * 1000 timeout: 20 * 1000
}; };
const res = await axios.post('/user/whitelabel/create-interactions', {}, opts); const res = await axios.post('/user/whitelabel/create-interactions', {}, opts);