From 8ed5a4b1dd04932931c182ae83a958774d993808 Mon Sep 17 00:00:00 2001 From: FIGBERT Date: Sat, 24 Jun 2023 00:54:08 +0300 Subject: [PATCH] Add headless initial log-in flow This offloads a lot of intial processing if you're planning on running gomuks on low-power hardware, but have access to high-power hardware for the sync (see: large accounts on the beepberry). A few planned improvements to this mode: - Exit gracefully if the transfer directory already exists - Make sure key presses are disabled during sync - Add verification to flow --- gomuks.go | 22 ++++++++++++++++++++-- main.go | 13 +++++++++++-- matrix/matrix.go | 33 +++++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/gomuks.go b/gomuks.go index a68a699..4b24422 100644 --- a/gomuks.go +++ b/gomuks.go @@ -76,14 +76,14 @@ type Gomuks struct { // NewGomuks creates a new Gomuks instance with everything initialized, // but does not start it. -func NewGomuks(uiProvider ifc.UIProvider, configDir, dataDir, cacheDir, downloadDir string) *Gomuks { +func NewGomuks(uiProvider ifc.UIProvider, configDir, dataDir, cacheDir, downloadDir string, isHeadless bool) *Gomuks { gmx := &Gomuks{ stop: make(chan bool, 1), } gmx.config = config.NewConfig(configDir, dataDir, cacheDir, downloadDir) gmx.ui = uiProvider(gmx) - gmx.matrix = matrix.NewContainer(gmx) + gmx.matrix = matrix.NewContainer(gmx, isHeadless) gmx.config.LoadAll() gmx.ui.Init() @@ -136,6 +136,24 @@ func (gmx *Gomuks) internalStop(save bool) { if save { gmx.Save() } + if gmx.matrix.IsHeadless() { + fmt.Println("🚚📦📦 gomuks is ready to go 🚚📦📦") + fmt.Println("⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒⇒") + fmt.Println() + fmt.Println("1.") + fmt.Println("copy your new `transfer` folder to the target") + fmt.Println("location (perhaps a shiny new beepberry) with") + fmt.Println("cp, rsync, or equivalent.") + fmt.Println() + fmt.Println("2.") + fmt.Println("set the GOMUKS_ROOT environment variable to match") + fmt.Println("the new location of the directory and edit the") + fmt.Println("config file to reflect the changes.") + fmt.Println() + fmt.Println("recommended reading:") + fmt.Println("https://docs.mau.fi/gomuks/faq.html#where-does-gomuks-store-data") + fmt.Println("https://beepberry.sqfmi.com") + } debug.Print("Exiting process") os.Exit(0) } diff --git a/main.go b/main.go index bd13406..0122f5a 100644 --- a/main.go +++ b/main.go @@ -40,12 +40,13 @@ var wantVersion = flag.MakeFull("v", "version", "Show the version of gomuks", "f var clearCache = flag.MakeFull("c", "clear-cache", "Clear the cache directory instead of starting", "false").Bool() var skipVersionCheck = flag.MakeFull("s", "skip-version-check", "Skip the homeserver version checks at startup and login", "false").Bool() var clearData = flag.Make().LongKey("clear-all-data").Usage("Clear all data instead of starting").Default("false").Bool() +var logInForTransfer = flag.Make().LongKey("log-in-for-transfer").Usage("Log in and generate packaged data for transfer").Default("false").Bool() var wantHelp, _ = flag.MakeHelpFlag() func main() { flag.SetHelpTitles( "gomuks - A terminal Matrix client written in Go.", - "gomuks [-vcsh] [--clear-all-data]", + "gomuks [-vcsh] [--clear-all-data|--log-in-for-transfer]", ) err := flag.Parse() if err != nil { @@ -58,6 +59,12 @@ func main() { fmt.Println(VersionString) return } + if *logInForTransfer { + if currentDir, err := os.Getwd(); err == nil { + os.Setenv("GOMUKS_ROOT", filepath.Join(currentDir, "transfer")) + } + } + debugDir := os.Getenv("DEBUG_DIR") if len(debugDir) > 0 { debug.LogDirectory = debugDir @@ -103,7 +110,7 @@ func main() { debug.Print("Download directory:", downloadDir) matrix.SkipVersionCheck = *skipVersionCheck - gmx := NewGomuks(MainUIProvider, configDir, dataDir, cacheDir, downloadDir) + gmx := NewGomuks(MainUIProvider, configDir, dataDir, cacheDir, downloadDir, *logInForTransfer) if *clearCache { debug.Print("Clearing cache as requested by CLI flag") @@ -117,6 +124,8 @@ func main() { _ = os.RemoveAll(gmx.config.Dir) fmt.Printf("Cleared cache at %s, data at %s and config at %s\n", gmx.config.CacheDir, gmx.config.DataDir, gmx.config.Dir) return + } else if *logInForTransfer { + debug.Print("Initializing in headless mode as requested by CLI flag") } gmx.Start() diff --git a/matrix/matrix.go b/matrix/matrix.go index 3a9affe..c18c86c 100644 --- a/matrix/matrix.go +++ b/matrix/matrix.go @@ -60,18 +60,20 @@ type Container struct { ui ifc.GomuksUI config *config.Config history *HistoryManager - running bool - stop chan bool + running, + headless bool + stop chan bool typing int64 } // NewContainer creates a new Container for the given Gomuks instance. -func NewContainer(gmx ifc.Gomuks) *Container { +func NewContainer(gmx ifc.Gomuks, isHeadless bool) *Container { c := &Container{ - config: gmx.Config(), - ui: gmx.UI(), - gmx: gmx, + config: gmx.Config(), + ui: gmx.UI(), + gmx: gmx, + headless: isHeadless, } return c @@ -82,6 +84,10 @@ func (c *Container) Client() *mautrix.Client { return c.client } +func (c *Container) IsHeadless() bool { + return c.headless +} + type mxLogger struct{} func (log mxLogger) Debugfln(message string, args ...interface{}) { @@ -426,6 +432,9 @@ func (c *Container) OnLogin() { c.syncer.Progress.Close() c.syncer.Progress = StubSyncingModal{} c.syncer.FirstDoneCallback = nil + if c.headless { + c.gmx.Stop(true) + } } } c.syncer.InitDoneCallback = func() { @@ -439,9 +448,11 @@ func (c *Container) OnLogin() { c.config.Rooms.ForceClean() debug.Print("Saving all data") c.config.SaveAll() - debug.Print("Adding rooms to UI") - c.ui.MainView().SetRooms(c.config.Rooms) - c.ui.Render() + if !c.headless { + debug.Print("Adding rooms to UI") + c.ui.MainView().SetRooms(c.config.Rooms) + c.ui.Render() + } // The initial sync can be a bit heavy, so we force run the GC here // after cleaning up rooms from memory above. debug.Print("Running GC") @@ -451,7 +462,9 @@ func (c *Container) OnLogin() { c.client.Syncer = c.syncer debug.Print("Setting existing rooms") - c.ui.MainView().SetRooms(c.config.Rooms) + if !c.headless { + c.ui.MainView().SetRooms(c.config.Rooms) + } debug.Print("OnLogin() done.") }