diff --git a/internal/frontend/cli/accounts.go b/internal/frontend/cli/accounts.go index afacb10c..890d4ccc 100644 --- a/internal/frontend/cli/accounts.go +++ b/internal/frontend/cli/accounts.go @@ -304,3 +304,30 @@ func (f *frontendCLI) configureAppleMail(c *ishell.Context) { f.Printf("Apple Mail configured for %v with address %v\n", user.Username, user.Addresses[0]) } + +func (f *frontendCLI) badEventSynchronize(c *ishell.Context) { + f.badEventFeedback(true) +} + +func (f *frontendCLI) badEventLogout(c *ishell.Context) { + f.badEventFeedback(false) +} + +func (f *frontendCLI) badEventFeedback(doResync bool) { + if f.badUserID == "" { + f.Printf("Error: There was no unresolved bad event.") + return + } + + action := "synchronize" + if !doResync { + action = "logout" + } + + if err := f.bridge.SendBadEventUserFeedback(context.Background(), f.badUserID, doResync); err != nil { + f.Printf("Error: failed to send %s feedback: %w", action, err) + return + } + + f.badUserID = "" +} diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 39d34244..89749c6c 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -37,6 +37,8 @@ type frontendCLI struct { bridge *bridge.Bridge restarter *restarter.Restarter + + badUserID string } // New returns a new CLI frontend configured with the given options. @@ -45,6 +47,7 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e Shell: ishell.New(), bridge: bridge, restarter: restarter, + badUserID: "", } // Clear commands. @@ -256,6 +259,22 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e Completer: fe.completeUsernames, }) + badEventCmd := &ishell.Cmd{ + Name: "bad-event", + Help: "manage actions when bad event error occurs", + } + badEventCmd.AddCmd(&ishell.Cmd{ + Name: "synchronize", + Help: "synchronize your local database to resolve the bad event error", + Func: fe.badEventSynchronize, + }) + badEventCmd.AddCmd(&ishell.Cmd{ + Name: "logout", + Help: "logout to deal with bad event error later", + Func: fe.badEventLogout, + }) + fe.AddCmd(badEventCmd) + go fe.watchEvents(eventCh) return fe @@ -301,7 +320,16 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funle return } - f.Printf("User %s received a bad event and was logged out.\n", user.Username) + f.badUserID = event.UserID + + f.Printf("\nInternal Error\n\n") + f.Printf("Bridge ran into an internal error and it is not able proceed with %s.\n", user.Username) + f.Printf("Synchronize your local database now or logout to do it later.\n") + f.Printf("Synchronization time depends on the size of your mailbox.\n") + f.Printf("\n\n") + f.Printf("The allowed actions are:") + f.Printf("* bad-event synchronize") + f.Printf("* bad-event logout") case events.UserAddressUpdated: user, err := f.bridge.GetUserInfo(event.UserID)