telegabber/telegram/loginwizard.go

118 lines
3.1 KiB
Go

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()
}
}