implement console commands

This commit is contained in:
Lukas Schulte Pelkum 2023-06-17 21:52:09 +02:00
parent e2c9454430
commit b2ad618781
No known key found for this signature in database
GPG Key ID: AB3985CECFAFC962
6 changed files with 173 additions and 2 deletions

View File

@ -0,0 +1,27 @@
package main
import (
"context"
"fmt"
"time"
)
func (router *consoleCommandRouter) Cleanup(args []string) {
if len(args) == 0 {
fmt.Println("Expected 1 argument.")
return
}
lifetime, err := time.ParseDuration(args[0])
if err != nil {
fmt.Printf("Could not parse duration: %s.\n", err.Error())
return
}
amount, err := router.Storage.Pastes().DeleteOlderThan(context.Background(), lifetime)
if err != nil {
if err != nil {
fmt.Printf("Could not delete pastes: %s.\n", err.Error())
return
}
}
fmt.Printf("Deleted %d pastes older than %s.\n", amount, lifetime)
}

View File

@ -0,0 +1,28 @@
package main
import (
"context"
"fmt"
)
func (router *consoleCommandRouter) Delete(args []string) {
if len(args) == 0 {
fmt.Println("Expected 1 argument.")
return
}
pasteID := args[0]
paste, err := router.Storage.Pastes().FindByID(context.Background(), pasteID)
if err != nil {
fmt.Printf("Could not look up paste: %s.\n", err.Error())
return
}
if paste == nil {
fmt.Printf("Invalid paste ID: %s.\n", pasteID)
return
}
if err := router.Storage.Pastes().DeleteByID(context.Background(), pasteID); err != nil {
fmt.Printf("Could not delete paste: %s.\n", err.Error())
return
}
fmt.Printf("Deleted paste %s.\n", pasteID)
}

View File

@ -0,0 +1,73 @@
package main
import (
"bufio"
"fmt"
"github.com/lus/pasty/internal/config"
"github.com/lus/pasty/internal/storage"
"github.com/rs/zerolog/log"
"os"
"regexp"
"strings"
"syscall"
)
var whitespaceRegex = regexp.MustCompile("\\s+")
type consoleCommandRouter struct {
Config *config.Config
Storage storage.Driver
}
func (router *consoleCommandRouter) Listen() {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
input, err := reader.ReadString('\n')
if err != nil {
log.Err(err).Msg("Could not read console input.")
continue
}
commandData := strings.Split(whitespaceRegex.ReplaceAllString(strings.TrimSpace(input), " "), " ")
if len(commandData) == 0 {
fmt.Println("Invalid command.")
continue
}
handle := strings.ToLower(commandData[0])
var args []string
if len(commandData) > 1 {
args = commandData[1:]
}
switch handle {
case "help":
fmt.Println("Available commands:")
fmt.Println(" help : Shows this overview")
fmt.Println(" stop : Stops the application")
fmt.Println(" setmodtoken <id> <token> : Changes the modification token of the paste with ID <id> to <token>")
fmt.Println(" delete <id> : Deletes the paste with ID <id>")
fmt.Println(" cleanup <duration> : Deletes all pastes that are older than <duration>")
break
case "stop":
if err := syscall.Kill(syscall.Getpid(), syscall.SIGINT); err != nil {
fmt.Printf("Could not send interrupt signal: %s.\nUse Ctrl+C instead.\n", err.Error())
break
}
return
case "setmodtoken":
router.SetModificationToken(args)
break
case "delete":
router.Delete(args)
break
case "cleanup":
router.Cleanup(args)
break
default:
fmt.Println("Invalid command.")
break
}
}
}

View File

@ -0,0 +1,34 @@
package main
import (
"context"
"fmt"
)
func (router *consoleCommandRouter) SetModificationToken(args []string) {
if len(args) < 2 {
fmt.Println("Expected 2 arguments.")
return
}
pasteID := args[0]
newToken := args[1]
paste, err := router.Storage.Pastes().FindByID(context.Background(), pasteID)
if err != nil {
fmt.Printf("Could not look up paste: %s.\n", err.Error())
return
}
if paste == nil {
fmt.Printf("Invalid paste ID: %s.\n", pasteID)
return
}
paste.ModificationToken = newToken
if err := paste.HashModificationToken(); err != nil {
fmt.Printf("Could not hash modification token: %s.\n", err.Error())
return
}
if err := router.Storage.Pastes().Upsert(context.Background(), paste); err != nil {
fmt.Printf("Could not update paste: %s.\n", err.Error())
return
}
fmt.Printf("Changed modification token of paste %s to %s.\n", pasteID, newToken)
}

View File

@ -132,8 +132,16 @@ func main() {
}
}()
// Wait for an interrupt signal
log.Info().Msg("The application has been started. Use Ctrl+C to shut it down.")
if !cfg.ConsoleCommandsEnabled {
log.Info().Msg("The application has been started. Use Ctrl+C to shut it down.")
} else {
log.Info().Msg("The application has been started and listens to console commands. Use Ctrl+C or 'stop' to shut it down.")
go (&consoleCommandRouter{
Config: cfg,
Storage: driver,
}).Listen()
}
shutdownChan := make(chan os.Signal, 1)
signal.Notify(shutdownChan, os.Interrupt)
<-shutdownChan

View File

@ -18,6 +18,7 @@ type Config struct {
ModificationTokenCharset string `default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" split_words:"true"`
RateLimit string `default:"30-M" split_words:"true"`
PasteLengthCap int `default:"50000" split_words:"true"`
ConsoleCommandsEnabled bool `default:"true" split_words:"true"`
Cleanup *CleanupConfig
Reports *ReportConfig
Postgres *PostgresConfig