@@ 6,8 6,10 @@ import (
"fmt"
"io/ioutil"
"os"
+ "syscall"
"github.com/kyoh86/xdg"
+ "golang.org/x/crypto/ssh/terminal"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/id"
)
@@ 56,48 58,68 @@ func stripNewline(s string) string {
}
func inquireForAuthInfo() (authInfo *AuthInfo, err error) {
- var (
- password string
- reader = bufio.NewReader(os.Stdin)
- )
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Println(`============================== DISCLAIMER ==============================
+tallyard won't make any attempts to read your personal Matrix messages.
+It uses a Matrix filter that restricts messages it reads to only those
+with a type beginning with "xyz.tallyard.". If you're skeptical, I
+encourage you to read the source code.
+========================================================================
+`)
+
+try:
authInfo = &AuthInfo{}
- for authInfo.Homeserver == "" || authInfo.Homeserver == "\n" {
- fmt.Print("enter homeserver: ")
- authInfo.Homeserver, err = reader.ReadString('\n')
- if err != nil {
- return nil, fmt.Errorf("error reading homeserver: %s", err)
- }
+ fmt.Print("Enter full Matrix username (@localpart:domain): ")
+ username, err := reader.ReadString('\n')
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error reading username: %s\n", err)
+ goto try
+ }
+ username = stripNewline(username)
+ localPart, serverName, err := id.UserID(username).Parse()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error parsing username: %s\n", err)
+ goto try
}
- authInfo.Homeserver = stripNewline(authInfo.Homeserver)
+ authInfo.Username = localPart
- for authInfo.Username == "" || authInfo.Username == "\n" {
- fmt.Print("enter username: ")
- authInfo.Username, err = reader.ReadString('\n')
+ wellKnownResp, err := mautrix.DiscoverClientAPI(serverName)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error discovering homeserver: %s\n", err)
+ goto try
+ }
+ if wellKnownResp == nil {
+ fmt.Println("You should contact your homeserver sysadmin to setup /.well-known/matrix/client")
+ fmt.Print("Enter homeserver: ")
+ homeserver, err := reader.ReadString('\n')
if err != nil {
- return nil, fmt.Errorf("error reading username: %s", err)
+ fmt.Printf("Error reading homeserver: %s\n", err)
+ goto try
}
+ authInfo.Homeserver = stripNewline(homeserver)
+ } else {
+ authInfo.Homeserver = wellKnownResp.Homeserver.BaseURL
}
- authInfo.Username = stripNewline(authInfo.Username)
- for password == "" || password == "\n" {
- fmt.Print("enter password: ")
- password, err = reader.ReadString('\n')
- if err != nil {
- return nil, fmt.Errorf("error reading password: %s", err)
- }
+ fmt.Print("Enter password: ")
+ rawPassword, err := terminal.ReadPassword(syscall.Stdin)
+ if err != nil {
+ fmt.Printf("Error reading password: %s\n", err)
+ goto try
}
- password = stripNewline(password)
client, err := mautrix.NewClient(authInfo.Homeserver, "", "")
if err != nil {
return nil, fmt.Errorf("error creating mautrix client: %s", err)
}
+ // entering a password doesn't insert a newline
+ fmt.Printf("\nAttempting login...\n")
respLogin, err := client.Login(&mautrix.ReqLogin{
Type: "m.login.password",
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: authInfo.Username},
- Password: password,
+ Password: string(rawPassword),
StoreCredentials: true,
})
if err != nil {