Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
423 changes: 176 additions & 247 deletions bot/button/handlers/gdprconfirm.go

Large diffs are not rendered by default.

46 changes: 30 additions & 16 deletions bot/button/handlers/gdprconfirmview.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package handlers

import (
"fmt"
"strings"

"github.com/TicketsBot-cloud/gdl/objects/interaction/component"
Expand All @@ -19,6 +18,8 @@ const (
GDPRSpecificTranscripts
GDPRAllMessages
GDPRSpecificMessages
GDPRExportGuild
GDPRExportUser
)

type GDPRConfirmationData struct {
Expand Down Expand Up @@ -57,9 +58,33 @@ func buildGDPRConfirmationView(ctx interface{}, locale *i18n.Locale, data GDPRCo

case GDPRSpecificMessages:
content = i18n.GetMessage(locale, i18n.GdprConfirmSpecificMessages, data.GuildNames[0], data.TicketIdsStr)

case GDPRExportGuild:
if len(data.GuildIds) == 1 {
content = i18n.GetMessage(locale, i18n.GdprConfirmExportGuild, data.GuildNames[0])
} else {
serversList := strings.Join(data.GuildNames, "\n* ")
content = i18n.GetMessage(locale, i18n.GdprConfirmExportGuildMulti, serversList)
}

case GDPRExportUser:
content = i18n.GetMessage(locale, i18n.GdprConfirmExportUser)
}

isExport := data.RequestType == GDPRExportGuild || data.RequestType == GDPRExportUser

if !isExport {
content += i18n.GetMessage(locale, i18n.GdprConfirmWarning)
}

content += i18n.GetMessage(locale, i18n.GdprConfirmWarning)
buttonStyle := component.ButtonStyleDanger
buttonLabel := i18n.GetMessage(locale, i18n.GdprConfirmButton)
buttonEmoji := utils.BuildEmoji("⚠️")
if isExport {
buttonStyle = component.ButtonStylePrimary
buttonLabel = i18n.GetMessage(locale, i18n.GdprConfirmExportButton)
buttonEmoji = utils.BuildEmoji("📦")
}

innerComponents := []component.Component{
component.BuildTextDisplay(component.TextDisplay{
Expand All @@ -68,10 +93,10 @@ func buildGDPRConfirmationView(ctx interface{}, locale *i18n.Locale, data GDPRCo
component.BuildSeparator(component.Separator{}),
component.BuildActionRow(
component.BuildButton(component.Button{
Label: i18n.GetMessage(locale, i18n.GdprConfirmButton),
Label: buttonLabel,
CustomId: data.ConfirmButtonId,
Style: component.ButtonStyleDanger,
Emoji: utils.BuildEmoji("⚠️"),
Style: buttonStyle,
Emoji: buttonEmoji,
}),
),
}
Expand All @@ -89,14 +114,3 @@ func buildGDPRConfirmationView(ctx interface{}, locale *i18n.Locale, data GDPRCo

return []component.Component{container}
}

func buildAllMessagesConfirmationComponents(ctx *cmdcontext.ButtonContext, locale *i18n.Locale, userId uint64) []component.Component {
data := GDPRConfirmationData{
RequestType: GDPRAllMessages,
UserId: userId,
Locale: locale,
ConfirmButtonId: fmt.Sprintf("gdpr_confirm_all_messages_%s", locale.IsoShortCode),
}

return buildGDPRConfirmationView(ctx, locale, data)
}
141 changes: 141 additions & 0 deletions bot/button/handlers/gdprexportbutton.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package handlers

import (
"fmt"
"strings"

"github.com/TicketsBot-cloud/gdl/objects/interaction"
"github.com/TicketsBot-cloud/gdl/objects/interaction/component"
"github.com/TicketsBot-cloud/worker/bot/button"
"github.com/TicketsBot-cloud/worker/bot/button/registry"
"github.com/TicketsBot-cloud/worker/bot/button/registry/matcher"
"github.com/TicketsBot-cloud/worker/bot/command"
cmdcontext "github.com/TicketsBot-cloud/worker/bot/command/context"
"github.com/TicketsBot-cloud/worker/bot/customisation"
"github.com/TicketsBot-cloud/worker/bot/gdprrelay"
"github.com/TicketsBot-cloud/worker/bot/redis"
"github.com/TicketsBot-cloud/worker/bot/utils"
"github.com/TicketsBot-cloud/worker/i18n"
)

type GDPRExportGuildHandler struct{}

func (h *GDPRExportGuildHandler) Matcher() matcher.Matcher {
return matcher.NewFuncMatcher(func(customId string) bool {
return strings.HasPrefix(customId, "gdpr_export_guild_")
})
}

func (h *GDPRExportGuildHandler) Properties() registry.Properties {
return gdprProperties()
}

func (h *GDPRExportGuildHandler) Execute(ctx *cmdcontext.ButtonContext) {
locale := utils.ExtractLanguageFromCustomId(ctx.InteractionData.CustomId)

if !gdprrelay.IsWorkerAlive(redis.Client) {
container := utils.BuildGDPRWorkerOfflineView(ctx, locale)
ctx.Edit(command.NewMessageResponseWithComponents([]component.Component{container}))
return
}

guilds, err := getOwnedGuildsWithTranscripts(ctx, ctx.UserId())
if err != nil {
ctx.HandleError(err)
return
}

if len(guilds) == 0 {
ctx.ReplyRaw(customisation.Red, "Error", i18n.GetMessage(locale, i18n.GdprErrorNoServers))
return
}

var modal interaction.ModalResponseData
if len(guilds) > 25 {
modal = buildExportGuildTextModal(locale)
} else {
modal = buildExportGuildModal(locale, guilds)
}

ctx.Modal(button.ResponseModal{Data: modal})
}

func buildExportGuildModal(locale *i18n.Locale, guilds []guildInfo) interaction.ModalResponseData {
options := buildGuildSelectOptions(guilds)
minVal, maxVal := 1, len(options)
if maxVal > 25 {
maxVal = 25
}

return interaction.ModalResponseData{
CustomId: fmt.Sprintf("gdpr_modal_export_guild_%s", locale.IsoShortCode),
Title: i18n.GetMessage(locale, i18n.GdprModalExportGuildTitle),
Components: []component.Component{
component.BuildLabel(component.Label{
Label: i18n.GetMessage(locale, i18n.GdprModalSelectServers),
Component: component.BuildSelectMenu(component.SelectMenu{
CustomId: "server_ids",
Placeholder: i18n.GetMessage(locale, i18n.GdprModalSelectServers),
MinValues: &minVal,
MaxValues: &maxVal,
Options: options,
}),
}),
},
}
}

func buildExportGuildTextModal(locale *i18n.Locale) interaction.ModalResponseData {
return interaction.ModalResponseData{
CustomId: fmt.Sprintf("gdpr_modal_export_guild_text_%s", locale.IsoShortCode),
Title: i18n.GetMessage(locale, i18n.GdprModalExportGuildTitle),
Components: []component.Component{
component.BuildLabel(component.Label{
Label: i18n.GetMessage(locale, i18n.GdprModalServerIdsLabel),
Component: component.BuildInputText(component.InputText{
CustomId: "server_ids",
Style: component.TextStyleParagraph,
Placeholder: utils.Ptr(i18n.GetMessage(locale, i18n.GdprModalServerIdsPlaceholder)),
Required: utils.Ptr(true),
MinLength: utils.Ptr(uint32(17)),
MaxLength: utils.Ptr(uint32(2000)),
}),
}),
},
}
}

// Skips guild selection and goes straight to confirmation.
type GDPRExportUserHandler struct{}

func (h *GDPRExportUserHandler) Matcher() matcher.Matcher {
return matcher.NewFuncMatcher(func(customId string) bool {
return strings.HasPrefix(customId, "gdpr_export_user_")
})
}

func (h *GDPRExportUserHandler) Properties() registry.Properties {
return gdprProperties()
}

func (h *GDPRExportUserHandler) Execute(ctx *cmdcontext.ButtonContext) {
locale := utils.ExtractLanguageFromCustomId(ctx.InteractionData.CustomId)

if !gdprrelay.IsWorkerAlive(redis.Client) {
container := utils.BuildGDPRWorkerOfflineView(ctx, locale)
ctx.Edit(command.NewMessageResponseWithComponents([]component.Component{container}))
return
}

data := GDPRConfirmationData{
RequestType: GDPRExportUser,
UserId: ctx.UserId(),
Locale: locale,
ConfirmButtonId: fmt.Sprintf("gdpr_confirm_export_user_%s", locale.IsoShortCode),
}

components := buildGDPRConfirmationView(ctx, locale, data)
if _, err := ctx.ReplyWith(command.NewMessageResponseWithComponents(components)); err != nil {
ctx.HandleError(err)
}
}
53 changes: 53 additions & 0 deletions bot/button/handlers/gdprguildcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package handlers

import (
"context"
"fmt"
"strings"

"github.com/TicketsBot-cloud/gdl/rest"
"github.com/TicketsBot-cloud/worker"
)

type guildCheck struct {
ValidIds []uint64
Names []string
Unreachable []string
NotOwner bool
}

// Deliberately not Worker.GetGuild: that answers from the cache, and a cached row outlives the bot
// being removed from the guild. Any fetch failure counts as unreachable.
func checkOwnedGuilds(ctx context.Context, w *worker.Context, userId uint64, guildIds []uint64) guildCheck {
var out guildCheck

for _, guildId := range guildIds {
guild, err := rest.GetGuild(ctx, w.Token, w.RateLimiter, guildId)
if err != nil {
out.Unreachable = append(out.Unreachable, formatGuildRef(guildId, ""))
continue
}

if guild.OwnerId != userId {
out.NotOwner = true
continue
}

out.Names = append(out.Names, formatGuildRef(guildId, guild.Name))
out.ValidIds = append(out.ValidIds, guildId)
}

return out
}

func (c guildCheck) UnreachableList() string {
return strings.Join(c.Unreachable, "\n* ")
}

func formatGuildRef(guildId uint64, name string) string {
if name == "" {
return fmt.Sprintf("%d", guildId)
}

return fmt.Sprintf("%s (ID: %d)", name, guildId)
}
Loading
Loading