269 lines
6.3 KiB
Go
269 lines
6.3 KiB
Go
package public
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"velox-bot/internal/commands/projects/shared"
|
|
"velox-bot/internal/db/services"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
var Projects = &discordgo.ApplicationCommand{
|
|
Name: "projects",
|
|
Description: "Manage and list ongoing projects",
|
|
Options: []*discordgo.ApplicationCommandOption{
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionSubCommand,
|
|
Name: "list",
|
|
Description: "List active projects with creators and helpers",
|
|
},
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionSubCommand,
|
|
Name: "create",
|
|
Description: "Create a new active project",
|
|
Options: []*discordgo.ApplicationCommandOption{
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionString,
|
|
Name: "name",
|
|
Description: "Project name",
|
|
Required: true,
|
|
},
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionString,
|
|
Name: "description",
|
|
Description: "Short description (optional)",
|
|
Required: false,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionSubCommand,
|
|
Name: "add-helper",
|
|
Description: "Add a helper to an existing project",
|
|
Options: []*discordgo.ApplicationCommandOption{
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionInteger,
|
|
Name: "project-id",
|
|
Description: "ID of the project",
|
|
Required: true,
|
|
},
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionUser,
|
|
Name: "user",
|
|
Description: "User to add as helper",
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func ProjectsHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
if !shared.RequireGuild(s, i) || !shared.RequireProjectsService(s, i) {
|
|
return
|
|
}
|
|
|
|
data := i.ApplicationCommandData()
|
|
if len(data.Options) == 0 {
|
|
handleList(s, i)
|
|
return
|
|
}
|
|
|
|
switch data.Options[0].Name {
|
|
case "list":
|
|
handleList(s, i)
|
|
case "create":
|
|
handleCreate(s, i)
|
|
case "add-helper":
|
|
handleAddHelper(s, i)
|
|
default:
|
|
shared.RespondEphemeral(s, i, "Unknown subcommand.")
|
|
}
|
|
}
|
|
|
|
func handleList(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
guildID, ok := shared.ParseGuildID(s, i)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
const limit = 25
|
|
items, err := services.Global.Projects.ListActiveWithMembers(context.Background(), guildID, limit)
|
|
if err != nil {
|
|
shared.RespondEphemeral(s, i, "Failed to load projects.")
|
|
return
|
|
}
|
|
if len(items) == 0 {
|
|
shared.RespondEphemeral(s, i, "There are no active projects at the moment.")
|
|
return
|
|
}
|
|
|
|
embed := &discordgo.MessageEmbed{
|
|
Title: "Active projects",
|
|
Description: "",
|
|
Color: 0x00bcd4,
|
|
}
|
|
|
|
for _, item := range items {
|
|
if item == nil || item.Project == nil {
|
|
continue
|
|
}
|
|
p := item.Project
|
|
name := p.Name
|
|
if name == "" {
|
|
name = "Unnamed project"
|
|
}
|
|
creatorMention := mentionUser(item.Creator)
|
|
|
|
var helpersMentions []string
|
|
for _, h := range item.Helpers {
|
|
helpersMentions = append(helpersMentions, mentionUser(h))
|
|
}
|
|
helpersText := "None"
|
|
if len(helpersMentions) > 0 {
|
|
helpersText = strings.Join(helpersMentions, ", ")
|
|
}
|
|
|
|
desc := "**Creator:** " + creatorMention + "\n" +
|
|
"**Helpers:** " + helpersText
|
|
if p.Description != "" {
|
|
desc += "\n" + p.Description
|
|
}
|
|
|
|
embed.Fields = append(embed.Fields, &discordgo.MessageEmbedField{
|
|
Name: name,
|
|
Value: desc,
|
|
})
|
|
}
|
|
|
|
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
|
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
|
Data: &discordgo.InteractionResponseData{
|
|
Embeds: []*discordgo.MessageEmbed{embed},
|
|
},
|
|
})
|
|
}
|
|
|
|
func mentionUser(id int64) string {
|
|
if id == 0 {
|
|
return "Unknown"
|
|
}
|
|
return "<@" + strconv.FormatInt(id, 10) + ">"
|
|
}
|
|
|
|
func handleCreate(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
if !shared.RequireManageGuild(s, i) {
|
|
return
|
|
}
|
|
|
|
guildID, ok := shared.ParseGuildID(s, i)
|
|
if !ok {
|
|
return
|
|
}
|
|
if i.Member == nil || i.Member.User == nil {
|
|
shared.RespondEphemeral(s, i, "Missing member info.")
|
|
return
|
|
}
|
|
|
|
data := i.ApplicationCommandData()
|
|
if len(data.Options) == 0 {
|
|
shared.RespondEphemeral(s, i, "Missing options.")
|
|
return
|
|
}
|
|
opt := data.Options[0]
|
|
|
|
var name, description string
|
|
for _, o := range opt.Options {
|
|
switch o.Name {
|
|
case "name":
|
|
name = o.StringValue()
|
|
case "description":
|
|
description = o.StringValue()
|
|
}
|
|
}
|
|
if strings.TrimSpace(name) == "" {
|
|
shared.RespondEphemeral(s, i, "Project name cannot be empty.")
|
|
return
|
|
}
|
|
|
|
creatorID, err := strconv.ParseInt(i.Member.User.ID, 10, 64)
|
|
if err != nil {
|
|
shared.RespondEphemeral(s, i, "Invalid user ID.")
|
|
return
|
|
}
|
|
|
|
id, err := services.Global.Projects.CreateProject(context.Background(), guildID, creatorID, name, description)
|
|
if err != nil {
|
|
shared.RespondEphemeral(s, i, "Failed to create project.")
|
|
return
|
|
}
|
|
|
|
shared.RespondEphemeral(s, i, "Created project **"+name+"** with ID `"+strconv.FormatInt(id, 10)+"`.")
|
|
}
|
|
|
|
func handleAddHelper(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
if !shared.RequireManageGuild(s, i) {
|
|
return
|
|
}
|
|
|
|
guildID, ok := shared.ParseGuildID(s, i)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
data := i.ApplicationCommandData()
|
|
if len(data.Options) == 0 {
|
|
shared.RespondEphemeral(s, i, "Missing options.")
|
|
return
|
|
}
|
|
opt := data.Options[0]
|
|
|
|
var projectID int64
|
|
var userID string
|
|
for _, o := range opt.Options {
|
|
switch o.Name {
|
|
case "project-id":
|
|
projectID = o.IntValue()
|
|
case "user":
|
|
if u := o.UserValue(s); u != nil {
|
|
userID = u.ID
|
|
}
|
|
}
|
|
}
|
|
if projectID <= 0 {
|
|
shared.RespondEphemeral(s, i, "Invalid project ID.")
|
|
return
|
|
}
|
|
if userID == "" {
|
|
shared.RespondEphemeral(s, i, "Invalid user.")
|
|
return
|
|
}
|
|
|
|
exists, err := services.Global.Projects.ProjectExistsInGuild(context.Background(), guildID, projectID)
|
|
if err != nil {
|
|
shared.RespondEphemeral(s, i, "Failed to load project.")
|
|
return
|
|
}
|
|
if !exists {
|
|
shared.RespondEphemeral(s, i, "Project `"+strconv.FormatInt(projectID, 10)+"` not found in this server.")
|
|
return
|
|
}
|
|
|
|
userID64, err := strconv.ParseInt(userID, 10, 64)
|
|
if err != nil {
|
|
shared.RespondEphemeral(s, i, "Invalid user ID.")
|
|
return
|
|
}
|
|
|
|
if err := services.Global.Projects.AddHelper(context.Background(), projectID, userID64); err != nil {
|
|
shared.RespondEphemeral(s, i, "Failed to add helper to project. ("+err.Error()+")")
|
|
return
|
|
}
|
|
|
|
shared.RespondEphemeral(s, i, "Added <@"+userID+"> as helper to project `"+strconv.FormatInt(projectID, 10)+"`.")
|
|
}
|
|
|