oups
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PanelConfig struct {
|
||||
ID int64
|
||||
Name string
|
||||
EmbedTitle string
|
||||
EmbedDescription sql.NullString
|
||||
EmbedColor string
|
||||
EmbedImage string
|
||||
EmbedThumbnail string
|
||||
GuildID string
|
||||
ChannelID sql.NullString
|
||||
MessageID sql.NullString
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Types []*PanelType
|
||||
}
|
||||
|
||||
type PanelType struct {
|
||||
ID int64
|
||||
PanelID int64
|
||||
Name string
|
||||
ButtonLabel string
|
||||
ButtonColor string
|
||||
ButtonEmoji string
|
||||
EmbedColor string
|
||||
EmbedTitle string
|
||||
EmbedText string
|
||||
ThumbnailURL string
|
||||
ImageURL string
|
||||
StaffRoleID string
|
||||
CategoryID string
|
||||
ClaimChannelID string
|
||||
LogChannelID string
|
||||
MaxPerUser int
|
||||
ClaimMode int
|
||||
ClaimReupMinutes int
|
||||
CloseRule string
|
||||
ModalEnabled bool
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type PanelConfigRepo struct{ db *sql.DB }
|
||||
|
||||
func NewPanelConfigRepo(db *sql.DB) *PanelConfigRepo { return &PanelConfigRepo{db: db} }
|
||||
|
||||
const panelCols = `id,name,embed_title,embed_description,embed_color,embed_image,embed_thumbnail,guild_id,channel_id,message_id,sort_order,created_at,updated_at`
|
||||
|
||||
const typeCols = `id,panel_id,name,button_label,button_color,button_emoji,embed_color,embed_title,embed_text,thumbnail_url,image_url,` +
|
||||
`staff_role_id,category_id,claim_channel_id,log_channel_id,max_per_user,claim_mode,claim_reup_minutes,close_rule,modal_enabled,sort_order,created_at,updated_at`
|
||||
|
||||
func (r *PanelConfigRepo) List(ctx context.Context) ([]*PanelConfig, error) {
|
||||
rows, err := r.db.QueryContext(ctx, `SELECT `+panelCols+` FROM panel_configs ORDER BY sort_order,name`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []*PanelConfig
|
||||
for rows.Next() {
|
||||
p, err := scanPanelConfig(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, p)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Load types for each panel in one extra pass
|
||||
for _, p := range out {
|
||||
p.Types, _ = r.ListTypes(ctx, p.ID)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) GetByID(ctx context.Context, id int64) (*PanelConfig, error) {
|
||||
row := r.db.QueryRowContext(ctx, `SELECT `+panelCols+` FROM panel_configs WHERE id=?`, id)
|
||||
var p PanelConfig
|
||||
err := row.Scan(&p.ID, &p.Name, &p.EmbedTitle, &p.EmbedDescription, &p.EmbedColor,
|
||||
&p.EmbedImage, &p.EmbedThumbnail, &p.GuildID, &p.ChannelID, &p.MessageID, &p.SortOrder, &p.CreatedAt, &p.UpdatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := r.ListTypes(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Types = types
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) Create(ctx context.Context, p *PanelConfig) error {
|
||||
now := time.Now().UTC()
|
||||
res, err := r.db.ExecContext(ctx,
|
||||
`INSERT INTO panel_configs(name,embed_title,embed_description,embed_color,embed_image,embed_thumbnail,guild_id,channel_id,sort_order,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
p.Name, p.EmbedTitle, p.EmbedDescription, p.EmbedColor, p.EmbedImage, p.EmbedThumbnail,
|
||||
p.GuildID, p.ChannelID, p.SortOrder, now, now)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.ID, _ = res.LastInsertId()
|
||||
p.CreatedAt = now
|
||||
p.UpdatedAt = now
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) Update(ctx context.Context, p *PanelConfig) error {
|
||||
now := time.Now().UTC()
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE panel_configs SET name=?,embed_title=?,embed_description=?,embed_color=?,embed_image=?,embed_thumbnail=?,
|
||||
guild_id=?,channel_id=?,sort_order=?,updated_at=? WHERE id=?`,
|
||||
p.Name, p.EmbedTitle, p.EmbedDescription, p.EmbedColor, p.EmbedImage, p.EmbedThumbnail,
|
||||
p.GuildID, p.ChannelID, p.SortOrder, now, p.ID)
|
||||
if err == nil {
|
||||
p.UpdatedAt = now
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) Delete(ctx context.Context, id int64) error {
|
||||
_, err := r.db.ExecContext(ctx, `DELETE FROM panel_configs WHERE id=?`, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// ReplaceTypes deletes all types for a panel and inserts the provided list.
|
||||
func (r *PanelConfigRepo) ReplaceTypes(ctx context.Context, panelID int64, types []*PanelType) error {
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback() //nolint
|
||||
if _, err := tx.ExecContext(ctx, `DELETE FROM panel_types WHERE panel_id=?`, panelID); err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
for i, t := range types {
|
||||
t.PanelID = panelID
|
||||
t.SortOrder = i
|
||||
res, err := tx.ExecContext(ctx,
|
||||
`INSERT INTO panel_types(panel_id,name,button_label,button_color,button_emoji,embed_color,embed_title,embed_text,thumbnail_url,image_url,
|
||||
staff_role_id,category_id,claim_channel_id,log_channel_id,max_per_user,claim_mode,claim_reup_minutes,close_rule,modal_enabled,sort_order,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
t.PanelID, t.Name, t.ButtonLabel, t.ButtonColor, t.ButtonEmoji, t.EmbedColor, t.EmbedTitle, t.EmbedText, t.ThumbnailURL, t.ImageURL,
|
||||
t.StaffRoleID, t.CategoryID, t.ClaimChannelID, t.LogChannelID, t.MaxPerUser, t.ClaimMode, t.ClaimReupMinutes,
|
||||
t.CloseRule, boolInt(t.ModalEnabled), t.SortOrder, now, now)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.ID, _ = res.LastInsertId()
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// ReorderTypes updates sort_order for the given type IDs in order.
|
||||
func (r *PanelConfigRepo) ReorderTypes(ctx context.Context, panelID int64, typeIDs []int64) error {
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback() //nolint
|
||||
for i, id := range typeIDs {
|
||||
if _, err := tx.ExecContext(ctx,
|
||||
`UPDATE panel_types SET sort_order=? WHERE id=? AND panel_id=?`, i, id, panelID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) SetDiscordMessage(ctx context.Context, id int64, channelID, messageID string) error {
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE panel_configs SET channel_id=?,message_id=?,updated_at=? WHERE id=?`,
|
||||
channelID, messageID, time.Now().UTC(), id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) GetByName(ctx context.Context, name string) (*PanelConfig, error) {
|
||||
row := r.db.QueryRowContext(ctx, `SELECT `+panelCols+` FROM panel_configs WHERE name=?`, name)
|
||||
var p PanelConfig
|
||||
err := row.Scan(&p.ID, &p.Name, &p.EmbedTitle, &p.EmbedDescription, &p.EmbedColor,
|
||||
&p.EmbedImage, &p.EmbedThumbnail, &p.GuildID, &p.ChannelID, &p.MessageID, &p.SortOrder, &p.CreatedAt, &p.UpdatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Types, _ = r.ListTypes(ctx, p.ID)
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) IsEmpty(ctx context.Context) (bool, error) {
|
||||
var count int
|
||||
err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM panel_configs`).Scan(&count)
|
||||
return count == 0, err
|
||||
}
|
||||
|
||||
// --- Types ---
|
||||
|
||||
func (r *PanelConfigRepo) ListTypes(ctx context.Context, panelID int64) ([]*PanelType, error) {
|
||||
rows, err := r.db.QueryContext(ctx,
|
||||
`SELECT `+typeCols+` FROM panel_types WHERE panel_id=? ORDER BY sort_order,name`, panelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []*PanelType
|
||||
for rows.Next() {
|
||||
t, err := scanPanelType(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, t)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) CreateType(ctx context.Context, t *PanelType) error {
|
||||
now := time.Now().UTC()
|
||||
res, err := r.db.ExecContext(ctx,
|
||||
`INSERT INTO panel_types(panel_id,name,button_label,button_color,button_emoji,embed_color,embed_title,embed_text,thumbnail_url,image_url,
|
||||
staff_role_id,category_id,claim_channel_id,log_channel_id,max_per_user,claim_mode,claim_reup_minutes,close_rule,modal_enabled,sort_order,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
t.PanelID, t.Name, t.ButtonLabel, t.ButtonColor, t.ButtonEmoji, t.EmbedColor, t.EmbedTitle, t.EmbedText, t.ThumbnailURL, t.ImageURL,
|
||||
t.StaffRoleID, t.CategoryID, t.ClaimChannelID, t.LogChannelID, t.MaxPerUser, t.ClaimMode, t.ClaimReupMinutes,
|
||||
t.CloseRule, boolInt(t.ModalEnabled), t.SortOrder, now, now)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.ID, _ = res.LastInsertId()
|
||||
t.CreatedAt = now
|
||||
t.UpdatedAt = now
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) UpdateType(ctx context.Context, t *PanelType) error {
|
||||
now := time.Now().UTC()
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE panel_types SET name=?,button_label=?,button_color=?,button_emoji=?,embed_color=?,embed_title=?,embed_text=?,thumbnail_url=?,image_url=?,
|
||||
staff_role_id=?,category_id=?,claim_channel_id=?,log_channel_id=?,max_per_user=?,claim_mode=?,claim_reup_minutes=?,close_rule=?,modal_enabled=?,sort_order=?,updated_at=?
|
||||
WHERE id=?`,
|
||||
t.Name, t.ButtonLabel, t.ButtonColor, t.ButtonEmoji, t.EmbedColor, t.EmbedTitle, t.EmbedText, t.ThumbnailURL, t.ImageURL,
|
||||
t.StaffRoleID, t.CategoryID, t.ClaimChannelID, t.LogChannelID, t.MaxPerUser, t.ClaimMode, t.ClaimReupMinutes,
|
||||
t.CloseRule, boolInt(t.ModalEnabled), t.SortOrder, now, t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PanelConfigRepo) DeleteType(ctx context.Context, id int64) error {
|
||||
_, err := r.db.ExecContext(ctx, `DELETE FROM panel_types WHERE id=?`, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func scanPanelConfig(rows *sql.Rows) (*PanelConfig, error) {
|
||||
var p PanelConfig
|
||||
err := rows.Scan(&p.ID, &p.Name, &p.EmbedTitle, &p.EmbedDescription, &p.EmbedColor,
|
||||
&p.EmbedImage, &p.EmbedThumbnail, &p.GuildID, &p.ChannelID, &p.MessageID, &p.SortOrder, &p.CreatedAt, &p.UpdatedAt)
|
||||
return &p, err
|
||||
}
|
||||
|
||||
func scanPanelType(rows *sql.Rows) (*PanelType, error) {
|
||||
var t PanelType
|
||||
var modalEnabled int
|
||||
err := rows.Scan(&t.ID, &t.PanelID, &t.Name, &t.ButtonLabel, &t.ButtonColor, &t.ButtonEmoji,
|
||||
&t.EmbedColor, &t.EmbedTitle, &t.EmbedText, &t.ThumbnailURL, &t.ImageURL,
|
||||
&t.StaffRoleID, &t.CategoryID, &t.ClaimChannelID, &t.LogChannelID,
|
||||
&t.MaxPerUser, &t.ClaimMode, &t.ClaimReupMinutes, &t.CloseRule, &modalEnabled, &t.SortOrder, &t.CreatedAt, &t.UpdatedAt)
|
||||
t.ModalEnabled = modalEnabled != 0
|
||||
return &t, err
|
||||
}
|
||||
Reference in New Issue
Block a user