173 lines
3.8 KiB
Go
173 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"codex-telegram-bot/internal/store"
|
|
)
|
|
|
|
func main() {
|
|
if err := run(context.Background(), os.Args[1:]); err != nil {
|
|
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run(ctx context.Context, args []string) error {
|
|
if len(args) == 0 {
|
|
return usage()
|
|
}
|
|
dbPath := os.Getenv("DB_PATH")
|
|
if dbPath == "" {
|
|
dbPath = filepath.Join("data", "bot.db")
|
|
}
|
|
st, err := store.Open(ctx, dbPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer st.Close()
|
|
|
|
switch args[0] {
|
|
case "allow-user":
|
|
return allowUser(ctx, st, args[1:])
|
|
case "remove-user":
|
|
return removeUser(ctx, st, args[1:])
|
|
case "list-users":
|
|
return listUsers(ctx, st)
|
|
case "add-workspace":
|
|
return addWorkspace(ctx, st, args[1:])
|
|
case "list-workspaces":
|
|
return listWorkspaces(ctx, st)
|
|
default:
|
|
return usage()
|
|
}
|
|
}
|
|
|
|
func usage() error {
|
|
return errors.New(`usage:
|
|
admin allow-user TELEGRAM_USER_ID [username] [notes...]
|
|
admin remove-user TELEGRAM_USER_ID
|
|
admin list-users
|
|
admin add-workspace ABSOLUTE_PATH [label] [--default]
|
|
admin list-workspaces`)
|
|
}
|
|
|
|
func allowUser(ctx context.Context, st *store.Store, args []string) error {
|
|
if len(args) < 1 {
|
|
return errors.New("allow-user requires TELEGRAM_USER_ID")
|
|
}
|
|
userID, err := strconv.ParseInt(args[0], 10, 64)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid telegram user id: %w", err)
|
|
}
|
|
username := ""
|
|
notes := ""
|
|
if len(args) >= 2 {
|
|
username = args[1]
|
|
}
|
|
if len(args) >= 3 {
|
|
notes = strings.Join(args[2:], " ")
|
|
}
|
|
if err := st.AddAllowedUser(ctx, userID, username, notes); err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("allowed user %d\n", userID)
|
|
return nil
|
|
}
|
|
|
|
func removeUser(ctx context.Context, st *store.Store, args []string) error {
|
|
if len(args) != 1 {
|
|
return errors.New("remove-user requires TELEGRAM_USER_ID")
|
|
}
|
|
userID, err := strconv.ParseInt(args[0], 10, 64)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid telegram user id: %w", err)
|
|
}
|
|
if err := st.RemoveAllowedUser(ctx, userID); err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("removed user %d\n", userID)
|
|
return nil
|
|
}
|
|
|
|
func listUsers(ctx context.Context, st *store.Store) error {
|
|
users, err := st.ListAllowedUsers(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(users) == 0 {
|
|
fmt.Println("no allowed users")
|
|
return nil
|
|
}
|
|
for _, user := range users {
|
|
if user.Username == "" && user.Notes == "" {
|
|
fmt.Printf("%d\n", user.TelegramUserID)
|
|
continue
|
|
}
|
|
fmt.Printf("%d\t%s\t%s\n", user.TelegramUserID, user.Username, user.Notes)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func addWorkspace(ctx context.Context, st *store.Store, args []string) error {
|
|
if len(args) < 1 {
|
|
return errors.New("add-workspace requires ABSOLUTE_PATH")
|
|
}
|
|
path := args[0]
|
|
label := ""
|
|
isDefault := false
|
|
for _, arg := range args[1:] {
|
|
if arg == "--default" {
|
|
isDefault = true
|
|
continue
|
|
}
|
|
if label == "" {
|
|
label = arg
|
|
continue
|
|
}
|
|
label += " " + arg
|
|
}
|
|
clean, err := store.ValidateWorkspacePath(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
info, err := os.Stat(clean)
|
|
if err != nil {
|
|
return fmt.Errorf("workspace path is not accessible: %w", err)
|
|
}
|
|
if !info.IsDir() {
|
|
return errors.New("workspace path must be a directory")
|
|
}
|
|
workspace, err := st.AddWorkspace(ctx, clean, label, isDefault)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("workspace %d\t%s\t%s\n", workspace.ID, workspace.Label, workspace.Path)
|
|
return nil
|
|
}
|
|
|
|
func listWorkspaces(ctx context.Context, st *store.Store) error {
|
|
workspaces, err := st.ListWorkspaces(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(workspaces) == 0 {
|
|
fmt.Println("no workspaces")
|
|
return nil
|
|
}
|
|
for _, workspace := range workspaces {
|
|
marker := ""
|
|
if workspace.IsDefault {
|
|
marker = "default"
|
|
}
|
|
fmt.Printf("%d\t%s\t%s\t%s\n", workspace.ID, marker, workspace.Label, workspace.Path)
|
|
}
|
|
return nil
|
|
}
|