package telegram import ( "dev.narayana.im/narayana/telegabber/xmpp/gateway" log "github.com/sirupsen/logrus" "github.com/zelenin/go-tdlib/client" ) type LoginStage string const ( LoginStageNone LoginStage = "" LoginStageLogin LoginStage = "login" LoginStageCode LoginStage = "code" LoginStagePassword LoginStage = "password" LoginStagePreset LoginStage = "preset" LoginStageMUC LoginStage = "muc" LoginStageSuccess LoginStage = "success" LoginStageCancel LoginStage = "cancel" ) // setLoginStage updates loginState and triggers session initialization on login sucess func (c *Client) setLoginStage(stage LoginStage) { c.loginStage = stage switch c.loginStage { case LoginStageSuccess, LoginStageCancel: c.locks.loginFinish.Done() } } // StartLoginWizard initiates a loginWizard object func (c *Client) StartLoginWizard(inCommand bool) { if c.loginWizard == nil { c.loginWizard = &loginWizardMetadata{ nextStage: make(chan LoginStage, 1), commandSent: inCommand, } } else { c.loginWizard.commandSent = inCommand } } // StopLoginWizard safely destroys the loginWizard object func (c *Client) StopLoginWizard() { c.locks.loginWizardReadLock.Lock() c.locks.loginWizardWriteLock.Lock() if c.loginWizard != nil { close(c.loginWizard.nextStage) c.loginWizard = nil } c.locks.loginWizardReadLock.Unlock() c.locks.loginWizardWriteLock.Unlock() } // GetLoginWizardNextStage waits for the next stage from the channel func (c *Client) GetLoginWizardNextStage() LoginStage { c.locks.loginWizardReadLock.Lock() defer c.locks.loginWizardReadLock.Unlock() if c.loginWizard != nil { if c.loginWizard.commandSent { log.Debugf("waiting for nextStage...") nextStage := <-c.loginWizard.nextStage c.loginWizard.commandSent = false c.loginWizard.chanBusy = false log.Debugf("yielded stage %v", nextStage) return nextStage } else { log.Debugf("commandSent is false") if c.lastAuthorizationStateType == client.TypeAuthorizationStateWaitPhoneNumber || c.lastAuthorizationStateType == client.TypeAuthorizationStateClosing || c.Session.Login == "" { return LoginStageLogin } switch c.lastAuthorizationStateType { case client.TypeAuthorizationStateWaitCode: return LoginStageCode case client.TypeAuthorizationStateWaitPassword: return LoginStagePassword } switch c.loginStage { case LoginStagePreset: return LoginStageMUC case LoginStageMUC: return LoginStageNone } } } return LoginStageNone } func (c *Client) wizardStageOrPrompt(stage LoginStage, message string) { log.Debugf("loginStage: %v stage: %v", c.loginStage, stage) if c.loginStage == stage { return } c.locks.loginWizardWriteLock.Lock() c.setLoginStage(stage) if c.loginWizard == nil { c.locks.loginWizardWriteLock.Unlock() if message != "" { gateway.SendServiceMessage(c.jid, message, c.xmpp) } } else { if !c.loginWizard.chanBusy { log.Debugf("writing wizard stage %v", stage) c.loginWizard.nextStage <- stage } else { log.Warnf("Skipping stage %v, wizard cannot keep up", stage) } c.loginWizard.chanBusy = true c.locks.loginWizardWriteLock.Unlock() } }