Command rework

This commit is contained in:
2026-08-18 21:20:31 +01:00
parent 5024af2789
commit 01dbb98450
11 changed files with 502 additions and 117 deletions
+60
View File
@@ -61,6 +61,35 @@ func (r *Repo) AddHelper(ctx context.Context, projectID, userID int64) error {
return err
}
func (r *Repo) DeactivateProject(ctx context.Context, guildID, projectID int64) error {
const q = `
UPDATE projects
SET is_active = FALSE
WHERE id = $1 AND guild_id = $2
`
_, err := r.db.ExecContext(ctx, q, projectID, guildID)
return err
}
// GetProject fetches a single project, scoped to guildID so a project ID
// from one server can't be used to reach into another's data.
func (r *Repo) GetProject(ctx context.Context, guildID, projectID int64) (*Project, error) {
const q = `
SELECT id, name, description, created_by
FROM projects
WHERE id = $1 AND guild_id = $2
`
row := r.db.QueryRowContext(ctx, q, projectID, guildID)
p := &Project{GuildID: guildID, IsActive: true}
if err := row.Scan(&p.ID, &p.Name, &p.Description, &p.CreatedBy); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return p, nil
}
func (r *Repo) ProjectExistsInGuild(ctx context.Context, guildID, projectID int64) (bool, error) {
const q = `
SELECT 1
@@ -79,6 +108,37 @@ func (r *Repo) ProjectExistsInGuild(ctx context.Context, guildID, projectID int6
}
}
// ListActiveProjects is a lighter version of ListActiveProjectsWithMembers,
// without the member-join query - for callers (like building a select menu
// of projects to pick from) that only need name/id, not creator/helpers.
func (r *Repo) ListActiveProjects(ctx context.Context, guildID int64, limit int) ([]*Project, error) {
const q = `
SELECT id, name, description, created_by
FROM projects
WHERE guild_id = $1 AND is_active = TRUE
ORDER BY created_at DESC
LIMIT $2
`
rows, err := r.db.QueryContext(ctx, q, guildID, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var out []*Project
for rows.Next() {
p := &Project{GuildID: guildID, IsActive: true}
if err := rows.Scan(&p.ID, &p.Name, &p.Description, &p.CreatedBy); err != nil {
return nil, err
}
out = append(out, p)
}
if err := rows.Err(); err != nil {
return nil, err
}
return out, nil
}
func (r *Repo) ListActiveProjectsWithMembers(ctx context.Context, guildID int64, limit int) ([]*ProjectWithMembers, error) {
const qProjects = `
SELECT id, name, description, created_by
+28
View File
@@ -113,3 +113,31 @@ func (r *Repo) SetNotificationChannel(ctx context.Context, guildID, channelID in
return err
}
// IsEnabled reports whether Twitch notifications are enabled for guildID.
// A guild with no twitch_config row yet defaults to enabled, matching the
// column's own DEFAULT TRUE - "never configured" and "explicitly on" are
// the same state until someone actually flips it off.
func (r *Repo) IsEnabled(ctx context.Context, guildID int64) (bool, error) {
const q = `SELECT enabled FROM twitch_config WHERE guild_id = $1`
var enabled bool
err := r.db.QueryRowContext(ctx, q, guildID).Scan(&enabled)
if err == sql.ErrNoRows {
return true, nil
}
if err != nil {
return false, err
}
return enabled, nil
}
func (r *Repo) SetEnabled(ctx context.Context, guildID int64, enabled bool) error {
const q = `
INSERT INTO twitch_config (guild_id, enabled)
VALUES ($1, $2)
ON CONFLICT (guild_id)
DO UPDATE SET enabled = EXCLUDED.enabled
`
_, err := r.db.ExecContext(ctx, q, guildID, enabled)
return err
}
+12
View File
@@ -26,7 +26,19 @@ func (s *Service) ListActiveWithMembers(ctx context.Context, guildID int64, limi
return s.repo.ListActiveProjectsWithMembers(ctx, guildID, limit)
}
func (s *Service) ListActive(ctx context.Context, guildID int64, limit int) ([]*projectsrepo.Project, error) {
return s.repo.ListActiveProjects(ctx, guildID, limit)
}
func (s *Service) ProjectExistsInGuild(ctx context.Context, guildID, projectID int64) (bool, error) {
return s.repo.ProjectExistsInGuild(ctx, guildID, projectID)
}
func (s *Service) GetProject(ctx context.Context, guildID, projectID int64) (*projectsrepo.Project, error) {
return s.repo.GetProject(ctx, guildID, projectID)
}
func (s *Service) DeactivateProject(ctx context.Context, guildID, projectID int64) error {
return s.repo.DeactivateProject(ctx, guildID, projectID)
}
+8
View File
@@ -59,6 +59,14 @@ func (s *Service) SetNotificationChannel(ctx context.Context, guildID, channelID
return s.repo.SetNotificationChannel(ctx, guildID, channelID)
}
func (s *Service) IsEnabled(ctx context.Context, guildID int64) (bool, error) {
return s.repo.IsEnabled(ctx, guildID)
}
func (s *Service) SetEnabled(ctx context.Context, guildID int64, enabled bool) error {
return s.repo.SetEnabled(ctx, guildID, enabled)
}
func (s *Service) IsUserStreaming(ctx context.Context, username string) (bool, error) {
type gqlRequest struct {
Query string `json:"query"`