Add command for Google account login
This commit is contained in:
parent
02f0b9e2ca
commit
20d05c90d3
2 changed files with 112 additions and 17 deletions
73
commands.go
73
commands.go
|
@ -17,6 +17,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -40,7 +41,8 @@ type WrappedCommandEvent struct {
|
|||
func (br *GMBridge) RegisterCommands() {
|
||||
proc := br.CommandProcessor.(*commands.Processor)
|
||||
proc.AddHandlers(
|
||||
cmdLogin,
|
||||
cmdLoginQR,
|
||||
cmdLoginGoogle,
|
||||
cmdDeleteSession,
|
||||
cmdLogout,
|
||||
cmdReconnect,
|
||||
|
@ -70,16 +72,17 @@ var (
|
|||
HelpSectionPortalManagement = commands.HelpSection{Name: "Portal management", Order: 20}
|
||||
)
|
||||
|
||||
var cmdLogin = &commands.FullHandler{
|
||||
Func: wrapCommand(fnLogin),
|
||||
Name: "login",
|
||||
var cmdLoginQR = &commands.FullHandler{
|
||||
Func: wrapCommand(fnLoginQR),
|
||||
Name: "login-qr",
|
||||
Aliases: []string{"login"},
|
||||
Help: commands.HelpMeta{
|
||||
Section: commands.HelpSectionAuth,
|
||||
Description: "Link the bridge to Google Messages on your Android phone as a web client.",
|
||||
Description: "Link the bridge to Google Messages on your Android phone by scanning a QR code.",
|
||||
},
|
||||
}
|
||||
|
||||
func fnLogin(ce *WrappedCommandEvent) {
|
||||
func fnLoginQR(ce *WrappedCommandEvent) {
|
||||
if ce.User.Session != nil {
|
||||
if ce.User.IsConnected() {
|
||||
ce.Reply("You're already logged in")
|
||||
|
@ -123,6 +126,64 @@ func fnLogin(ce *WrappedCommandEvent) {
|
|||
ce.ZLog.Trace().Msg("Login command finished")
|
||||
}
|
||||
|
||||
var cmdLoginGoogle = &commands.FullHandler{
|
||||
Func: wrapCommand(fnLoginGoogle),
|
||||
Name: "login-google",
|
||||
Aliases: []string{"login"},
|
||||
Help: commands.HelpMeta{
|
||||
Section: commands.HelpSectionAuth,
|
||||
Description: "Link the bridge to Google Messages on your Android phone by logging in with your Google account.",
|
||||
},
|
||||
}
|
||||
|
||||
func fnLoginGoogle(ce *WrappedCommandEvent) {
|
||||
if ce.User.Session != nil {
|
||||
if ce.User.IsConnected() {
|
||||
ce.Reply("You're already logged in")
|
||||
} else {
|
||||
ce.Reply("You're already logged in. Perhaps you wanted to `reconnect`?")
|
||||
}
|
||||
return
|
||||
} else if ce.User.pairSuccessChan != nil {
|
||||
ce.Reply("You already have a login in progress")
|
||||
return
|
||||
}
|
||||
ce.User.CommandState = &commands.CommandState{
|
||||
Next: commands.MinimalHandlerFunc(wrapCommand(fnLoginGoogleCookies)),
|
||||
Action: "Login",
|
||||
}
|
||||
ce.Reply("Send your Google cookies here, formatted as a key-value JSON object (see <https://docs.mau.fi/bridges/go/gmessages/authentication.html> for details)")
|
||||
}
|
||||
|
||||
func fnLoginGoogleCookies(ce *WrappedCommandEvent) {
|
||||
ce.User.CommandState = nil
|
||||
if ce.User.Session != nil {
|
||||
if ce.User.IsConnected() {
|
||||
ce.Reply("You're already logged in")
|
||||
} else {
|
||||
ce.Reply("You're already logged in. Perhaps you wanted to `reconnect`?")
|
||||
}
|
||||
return
|
||||
} else if ce.User.pairSuccessChan != nil {
|
||||
ce.Reply("You already have a login in progress")
|
||||
return
|
||||
}
|
||||
var cookies map[string]string
|
||||
err := json.Unmarshal([]byte(ce.RawArgs), &cookies)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to parse cookies: %v", err)
|
||||
return
|
||||
}
|
||||
err = ce.User.LoginGoogle(cookies, func(emoji string) {
|
||||
ce.Reply(emoji)
|
||||
})
|
||||
if err != nil {
|
||||
ce.Reply("Login failed: %v", err)
|
||||
} else {
|
||||
ce.Reply("Login successful")
|
||||
}
|
||||
}
|
||||
|
||||
func (user *User) sendQREdit(ce *WrappedCommandEvent, content *event.MessageEventContent, prevEvent id.EventID) id.EventID {
|
||||
if len(prevEvent) != 0 {
|
||||
content.SetEdit(prevEvent)
|
||||
|
|
56
user.go
56
user.go
|
@ -35,6 +35,7 @@ import (
|
|||
"maunium.net/go/mautrix/appservice"
|
||||
"maunium.net/go/mautrix/bridge"
|
||||
"maunium.net/go/mautrix/bridge/bridgeconfig"
|
||||
"maunium.net/go/mautrix/bridge/commands"
|
||||
"maunium.net/go/mautrix/bridge/status"
|
||||
"maunium.net/go/mautrix/event"
|
||||
"maunium.net/go/mautrix/format"
|
||||
|
@ -64,7 +65,8 @@ type User struct {
|
|||
spaceCreateLock sync.Mutex
|
||||
connLock sync.Mutex
|
||||
|
||||
BridgeState *bridge.BridgeStateQueue
|
||||
BridgeState *bridge.BridgeStateQueue
|
||||
CommandState *commands.CommandState
|
||||
|
||||
spaceMembershipChecked bool
|
||||
|
||||
|
@ -80,16 +82,25 @@ type User struct {
|
|||
pollErrorAlertSent bool
|
||||
phoneNotRespondingAlertSent bool
|
||||
|
||||
loginInProgress atomic.Bool
|
||||
pairSuccessChan chan struct{}
|
||||
ongoingLoginChan <-chan qrChannelItem
|
||||
loginChanReadLock sync.Mutex
|
||||
lastQRCode string
|
||||
cancelLogin func()
|
||||
loginInProgress atomic.Bool
|
||||
pairSuccessChan chan struct{}
|
||||
ongoingLoginChan <-chan qrChannelItem
|
||||
lastQRCode string
|
||||
cancelLogin func()
|
||||
|
||||
DoublePuppetIntent *appservice.IntentAPI
|
||||
}
|
||||
|
||||
func (user *User) GetCommandState() *commands.CommandState {
|
||||
return user.CommandState
|
||||
}
|
||||
|
||||
func (user *User) SetCommandState(state *commands.CommandState) {
|
||||
user.CommandState = state
|
||||
}
|
||||
|
||||
var _ commands.CommandingUser = (*User)(nil)
|
||||
|
||||
func (br *GMBridge) getUserByMXID(userID id.UserID, onlyIfExists bool) *User {
|
||||
_, isPuppet := br.ParsePuppetMXID(userID)
|
||||
if isPuppet || userID == br.Bot.UserID {
|
||||
|
@ -155,10 +166,6 @@ func (user *User) GetMXID() id.UserID {
|
|||
return user.MXID
|
||||
}
|
||||
|
||||
func (user *User) GetCommandState() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *GMBridge) GetUserByMXIDIfExists(userID id.UserID) *User {
|
||||
return br.getUserByMXID(userID, true)
|
||||
}
|
||||
|
@ -456,6 +463,33 @@ func (user *User) Login(maxAttempts int) (<-chan qrChannelItem, error) {
|
|||
return ch, nil
|
||||
}
|
||||
|
||||
func (user *User) LoginGoogle(cookies map[string]string, emojiCallback func(string)) error {
|
||||
user.connLock.Lock()
|
||||
defer user.connLock.Unlock()
|
||||
if user.Session != nil {
|
||||
return ErrAlreadyLoggedIn
|
||||
} else if !user.loginInProgress.CompareAndSwap(false, true) {
|
||||
return ErrLoginInProgress
|
||||
}
|
||||
if user.Client != nil {
|
||||
user.unlockedDeleteConnection()
|
||||
}
|
||||
pairSuccessChan := make(chan struct{})
|
||||
user.pairSuccessChan = pairSuccessChan
|
||||
authData := libgm.NewAuthData()
|
||||
authData.Cookies = cookies
|
||||
user.createClient(authData)
|
||||
Analytics.Track(user.MXID, "$login_start")
|
||||
err := user.Client.DoGaiaPairing(emojiCallback)
|
||||
if err != nil {
|
||||
user.unlockedDeleteConnection()
|
||||
user.pairSuccessChan = nil
|
||||
user.loginInProgress.Store(false)
|
||||
return fmt.Errorf("failed to connect to Google Messages: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) Connect() bool {
|
||||
user.connLock.Lock()
|
||||
defer user.connLock.Unlock()
|
||||
|
|
Loading…
Reference in a new issue