mirror of
https://github.com/Walter-Sparrow/lunar-tear.git
synced 2026-07-02 05:43:41 +03:00
Gacha pool overhaul and DB backup wizard
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"charm.land/huh/v2"
|
||||
"charm.land/lipgloss/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
gameDBPath = "db/game.db"
|
||||
backupDir = "db/backups"
|
||||
backupSuffix = ".bak"
|
||||
)
|
||||
|
||||
const banner = `
|
||||
_ _____
|
||||
| | _ _ _ _ __ _ _ _ |_ _|___ __ _ _ _
|
||||
| |_| || | ' \/ _` + "`" + ` | '_| | |/ -_)/ _` + "`" + ` | '_|
|
||||
|____\_,_|_||_\__,_|_| |_|\___|\__,_|_|
|
||||
|
||||
╭──────────────────────────────╮
|
||||
│ RESTORE │
|
||||
╰──────────────────────────────╯
|
||||
`
|
||||
|
||||
func main() {
|
||||
lipgloss.EnableLegacyWindowsANSI(os.Stdout)
|
||||
lipgloss.EnableLegacyWindowsANSI(os.Stderr)
|
||||
fmt.Print(banner)
|
||||
|
||||
chosen, ok := pickBackup()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !confirmOverwrite(chosen) {
|
||||
fmt.Println(" cancelled — nothing changed")
|
||||
return
|
||||
}
|
||||
if err := doRestore(chosen); err != nil {
|
||||
fmt.Fprintf(os.Stderr, " restore failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf(" restored %s from %s\n", gameDBPath, chosen)
|
||||
}
|
||||
|
||||
func pickBackup() (string, bool) {
|
||||
entries, err := os.ReadDir(backupDir)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, " no backups found in", backupDir)
|
||||
return "", false
|
||||
}
|
||||
var backups []string
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() && strings.HasPrefix(e.Name(), "game.db.") && strings.HasSuffix(e.Name(), backupSuffix) {
|
||||
backups = append(backups, e.Name())
|
||||
}
|
||||
}
|
||||
if len(backups) == 0 {
|
||||
fmt.Fprintln(os.Stderr, " no backups found in", backupDir)
|
||||
return "", false
|
||||
}
|
||||
sort.Slice(backups, func(i, j int) bool { return backups[i] > backups[j] })
|
||||
|
||||
options := make([]huh.Option[string], 0, len(backups)+1)
|
||||
for _, name := range backups {
|
||||
options = append(options, huh.NewOption(name, name))
|
||||
}
|
||||
options = append(options, huh.NewOption("Cancel", ""))
|
||||
|
||||
var chosen string
|
||||
if err := huh.NewSelect[string]().
|
||||
Title("Pick a backup to restore").
|
||||
Description("db/game.db will be replaced by the chosen file.").
|
||||
Options(options...).
|
||||
Value(&chosen).
|
||||
Run(); err != nil || chosen == "" {
|
||||
return "", false
|
||||
}
|
||||
return chosen, true
|
||||
}
|
||||
|
||||
func confirmOverwrite(chosen string) bool {
|
||||
confirm := false
|
||||
if err := huh.NewConfirm().
|
||||
Title("Overwrite db/game.db?").
|
||||
Description(fmt.Sprintf(
|
||||
"This will REPLACE db/game.db with %s.\n"+
|
||||
"Any progress since that backup will be lost.\n"+
|
||||
"(A fresh backup will be taken on the next ./wizard launch.)",
|
||||
chosen)).
|
||||
Affirmative("Yes, restore").
|
||||
Negative("Cancel").
|
||||
Value(&confirm).
|
||||
Run(); err != nil {
|
||||
return false
|
||||
}
|
||||
return confirm
|
||||
}
|
||||
|
||||
func doRestore(chosen string) error {
|
||||
src := filepath.Join(backupDir, chosen)
|
||||
if _, err := os.Stat(src); errors.Is(err, os.ErrNotExist) {
|
||||
return fmt.Errorf("%s no longer exists", src)
|
||||
}
|
||||
if err := copyFile(src, gameDBPath); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = os.Remove(gameDBPath + "-wal")
|
||||
_ = os.Remove(gameDBPath + "-shm")
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) error {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
if _, err := io.Copy(out, in); err != nil {
|
||||
return err
|
||||
}
|
||||
return out.Sync()
|
||||
}
|
||||
Reference in New Issue
Block a user