Initial discord remote auth support.
It works, but nothing is persisted yet as the user object needs some tweaking especially the database side.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
"gitlab.com/beeper/discord/consts"
|
"gitlab.com/beeper/discord/consts"
|
||||||
|
"gitlab.com/beeper/discord/remoteauth"
|
||||||
"gitlab.com/beeper/discord/version"
|
"gitlab.com/beeper/discord/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ type commands struct {
|
|||||||
globals
|
globals
|
||||||
|
|
||||||
Help helpCmd `kong:"cmd,help='Displays this message.'"`
|
Help helpCmd `kong:"cmd,help='Displays this message.'"`
|
||||||
|
Login loginCmd `kong:"cmd,help='Log in to Discord.'"`
|
||||||
Version versionCmd `kong:"cmd,help='Displays the version of the bridge.'"`
|
Version versionCmd `kong:"cmd,help='Displays the version of the bridge.'"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,3 +82,53 @@ func (c *versionCmd) Run(g *globals) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type loginCmd struct{}
|
||||||
|
|
||||||
|
func (l *loginCmd) Run(g *globals) error {
|
||||||
|
client, err := remoteauth.New()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
qrChan := make(chan string)
|
||||||
|
doneChan := make(chan struct{})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
code := <-qrChan
|
||||||
|
|
||||||
|
_, err := g.user.sendQRCode(g.bot, g.roomID, code)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(g.context.Stdout, "failed to generate the qrcode")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
if err := client.Dial(ctx, qrChan, doneChan); err != nil {
|
||||||
|
close(qrChan)
|
||||||
|
close(doneChan)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
<-doneChan
|
||||||
|
|
||||||
|
user, err := client.Result()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printfln(g.context.Stdout, "failed to log in")
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.user.User.ID = user.UserID
|
||||||
|
g.user.User.Discriminator = user.Discriminator
|
||||||
|
g.user.User.Username = user.Username
|
||||||
|
|
||||||
|
g.handler.log.Warnln("users:", user)
|
||||||
|
g.handler.log.Warnln("err:", err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
|
|
||||||
log "maunium.net/go/maulogger/v2"
|
log "maunium.net/go/maulogger/v2"
|
||||||
|
"maunium.net/go/mautrix/appservice"
|
||||||
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
"gitlab.com/beeper/discord/database"
|
"gitlab.com/beeper/discord/database"
|
||||||
@@ -91,3 +95,43 @@ func (u *User) SetManagementRoom(roomID id.RoomID) {
|
|||||||
func (u *User) HasSession() bool {
|
func (u *User) HasSession() bool {
|
||||||
return u.User.Session != nil
|
return u.User.Session != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) sendQRCode(bot *appservice.IntentAPI, roomID id.RoomID, code string) (id.EventID, error) {
|
||||||
|
url, err := u.uploadQRCode(code)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
content := event.MessageEventContent{
|
||||||
|
MsgType: event.MsgImage,
|
||||||
|
Body: code,
|
||||||
|
URL: url.CUString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := bot.SendMessageEvent(roomID, event.EventMessage, &content)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.EventID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) uploadQRCode(code string) (id.ContentURI, error) {
|
||||||
|
qrCode, err := qrcode.Encode(code, qrcode.Low, 256)
|
||||||
|
if err != nil {
|
||||||
|
u.log.Errorln("Failed to encode QR code:", err)
|
||||||
|
|
||||||
|
return id.ContentURI{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bot := u.bridge.as.BotClient()
|
||||||
|
|
||||||
|
resp, err := bot.UploadBytes(qrCode, "image/png")
|
||||||
|
if err != nil {
|
||||||
|
u.log.Errorln("Failed to upload QR code:", err)
|
||||||
|
|
||||||
|
return id.ContentURI{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.ContentURI, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ type User struct {
|
|||||||
MXID id.UserID
|
MXID id.UserID
|
||||||
ID string
|
ID string
|
||||||
|
|
||||||
|
Discriminator string
|
||||||
|
Username string
|
||||||
|
|
||||||
ManagementRoom id.RoomID
|
ManagementRoom id.RoomID
|
||||||
|
|
||||||
Session *discordgo.Session
|
Session *discordgo.Session
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -4,9 +4,13 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/kong v0.2.18
|
github.com/alecthomas/kong v0.2.18
|
||||||
|
github.com/bwmarrin/discordgo v0.23.2
|
||||||
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/lib/pq v1.9.0
|
github.com/lib/pq v1.9.0
|
||||||
github.com/lopezator/migrator v0.3.0
|
github.com/lopezator/migrator v0.3.0
|
||||||
github.com/mattn/go-sqlite3 v1.14.9
|
github.com/mattn/go-sqlite3 v1.14.9
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
maunium.net/go/maulogger/v2 v2.3.1
|
maunium.net/go/maulogger/v2 v2.3.1
|
||||||
maunium.net/go/mautrix v0.10.8
|
maunium.net/go/mautrix v0.10.8
|
||||||
@@ -14,10 +18,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/btcsuite/btcutil v1.0.2 // indirect
|
github.com/btcsuite/btcutil v1.0.2 // indirect
|
||||||
github.com/bwmarrin/discordgo v0.23.2 // indirect
|
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||||
|
|||||||
24
go.sum
24
go.sum
@@ -37,8 +37,6 @@ github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
|||||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lopezator/migrator v0.3.0 h1:VW/rR+J8NYwPdkBxjrFdjwejpgvP59LbmANJxXuNbuk=
|
github.com/lopezator/migrator v0.3.0 h1:VW/rR+J8NYwPdkBxjrFdjwejpgvP59LbmANJxXuNbuk=
|
||||||
github.com/lopezator/migrator v0.3.0/go.mod h1:bpVAVPkWSvTw8ya2Pk7E/KiNAyDWNImgivQY79o8/8I=
|
github.com/lopezator/migrator v0.3.0/go.mod h1:bpVAVPkWSvTw8ya2Pk7E/KiNAyDWNImgivQY79o8/8I=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@@ -50,46 +48,38 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
|
|
||||||
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
|
|
||||||
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d h1:1aflnvSoWWLI2k/dMUAl5lvU1YO4Mb4hz0gh+1rjcxU=
|
|
||||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
@@ -102,18 +92,12 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
maunium.net/go/maulogger/v2 v2.2.4/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
|
|
||||||
maunium.net/go/maulogger/v2 v2.3.1 h1:fwBYJne0pHvJrrIPHK+TAPfyxxbBEz46oVGez2x0ODE=
|
maunium.net/go/maulogger/v2 v2.3.1 h1:fwBYJne0pHvJrrIPHK+TAPfyxxbBEz46oVGez2x0ODE=
|
||||||
maunium.net/go/maulogger/v2 v2.3.1/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
|
maunium.net/go/maulogger/v2 v2.3.1/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
|
||||||
maunium.net/go/mautrix v0.9.27 h1:6MV6YSCGqfw8Rb0G1PHjTOkYkTY0vcZaz6wd+U+V1Is=
|
|
||||||
maunium.net/go/mautrix v0.9.27/go.mod h1:7IzKfWvpQtN+W2Lzxc0rLvIxFM3ryKX6Ys3S/ZoWbg8=
|
|
||||||
maunium.net/go/mautrix v0.10.7 h1:QV5vbCY4g50N7r1ihdG6zEPfaPn/EVYjM5H+qfLy4RM=
|
|
||||||
maunium.net/go/mautrix v0.10.7/go.mod h1:k4Ng5oci83MEbqPL6KOjPdbU7f8v01KlMjR/zTQ+7mA=
|
|
||||||
maunium.net/go/mautrix v0.10.8 h1:h64yDl8fMPk3j/tnkb6c5itSo/LZ1QSKQ3ze5zyanUg=
|
maunium.net/go/mautrix v0.10.8 h1:h64yDl8fMPk3j/tnkb6c5itSo/LZ1QSKQ3ze5zyanUg=
|
||||||
maunium.net/go/mautrix v0.10.8/go.mod h1:k4Ng5oci83MEbqPL6KOjPdbU7f8v01KlMjR/zTQ+7mA=
|
maunium.net/go/mautrix v0.10.8/go.mod h1:k4Ng5oci83MEbqPL6KOjPdbU7f8v01KlMjR/zTQ+7mA=
|
||||||
|
|||||||
54
remoteauth/README.md
Normal file
54
remoteauth/README.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Discord Remote Authentication
|
||||||
|
|
||||||
|
This library implements the desktop side of Discord's remote authentication
|
||||||
|
protocol.
|
||||||
|
|
||||||
|
It is completely based off of the
|
||||||
|
[Unofficial Discord API Documentation](https://luna.gitlab.io/discord-unofficial-docs/desktop_remote_auth.html).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
client, err := New()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error: %v\n", err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
qrChan := make(chan *qrcode.QRCode)
|
||||||
|
go func() {
|
||||||
|
qrCode := <-qrChan
|
||||||
|
fmt.Println(qrCode.ToSmallString(true))
|
||||||
|
}()
|
||||||
|
|
||||||
|
doneChan := make(chan struct{})
|
||||||
|
|
||||||
|
if err := client.Dial(ctx, qrChan, doneChan); err != nil {
|
||||||
|
close(qrChan)
|
||||||
|
close(doneChan)
|
||||||
|
|
||||||
|
fmt.Printf("dial error: %v\n", err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
<-doneChan
|
||||||
|
|
||||||
|
user, err := client.Result()
|
||||||
|
fmt.Printf("user: %q\n", user)
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
}
|
||||||
|
```
|
||||||
109
remoteauth/client.go
Normal file
109
remoteauth/client.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package remoteauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
URL string
|
||||||
|
Origin string
|
||||||
|
|
||||||
|
conn *websocket.Conn
|
||||||
|
|
||||||
|
qrChan chan string
|
||||||
|
doneChan chan struct{}
|
||||||
|
|
||||||
|
user User
|
||||||
|
err error
|
||||||
|
|
||||||
|
heartbeats int
|
||||||
|
closed bool
|
||||||
|
|
||||||
|
privateKey *rsa.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Discord remote auth client. qrChan is a channel that will
|
||||||
|
// receive the qrcode once it is available.
|
||||||
|
func New() (*Client, error) {
|
||||||
|
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
URL: "wss://remote-auth-gateway.discord.gg/?v=1",
|
||||||
|
Origin: "https://discord.com",
|
||||||
|
privateKey: privateKey,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dialo will start the QRCode login process. ctx may be used to abandon the
|
||||||
|
// process.
|
||||||
|
func (c *Client) Dial(ctx context.Context, qrChan chan string, doneChan chan struct{}) error {
|
||||||
|
header := http.Header{
|
||||||
|
"Origin": []string{c.Origin},
|
||||||
|
}
|
||||||
|
|
||||||
|
c.qrChan = qrChan
|
||||||
|
c.doneChan = doneChan
|
||||||
|
|
||||||
|
conn, _, err := websocket.DefaultDialer.DialContext(ctx, c.URL, header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.conn = conn
|
||||||
|
|
||||||
|
go c.processMessages()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Result() (User, error) {
|
||||||
|
return c.user, c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) close() error {
|
||||||
|
if c.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c.conn.WriteMessage(
|
||||||
|
websocket.CloseMessage,
|
||||||
|
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
c.closed = true
|
||||||
|
|
||||||
|
defer close(c.doneChan)
|
||||||
|
|
||||||
|
return c.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) write(p clientPacket) error {
|
||||||
|
payload, err := json.Marshal(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.conn.WriteMessage(websocket.TextMessage, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) decrypt(payload string) ([]byte, error) {
|
||||||
|
// Decode the base64 string.
|
||||||
|
raw, err := base64.StdEncoding.DecodeString(payload)
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt the data.
|
||||||
|
return rsa.DecryptOAEP(sha256.New(), nil, c.privateKey, raw, nil)
|
||||||
|
}
|
||||||
70
remoteauth/clientpackets.go
Normal file
70
remoteauth/clientpackets.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package remoteauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type clientPacket interface {
|
||||||
|
send(client *Client) error
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Heartbeat
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type clientHeartbeat struct {
|
||||||
|
OP string `json:"op"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *clientHeartbeat) send(client *Client) error {
|
||||||
|
// make sure our op string is set
|
||||||
|
h.OP = "heartbeat"
|
||||||
|
|
||||||
|
client.heartbeats += 1
|
||||||
|
if client.heartbeats > 2 {
|
||||||
|
return fmt.Errorf("server failed to acknowledge our heartbeats")
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.write(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Init
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type clientInit struct {
|
||||||
|
OP string `json:"op"`
|
||||||
|
EncodedPublicKey string `json:"encoded_public_key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *clientInit) send(client *Client) error {
|
||||||
|
i.OP = "init"
|
||||||
|
|
||||||
|
pubkey := client.privateKey.Public()
|
||||||
|
|
||||||
|
raw, err := x509.MarshalPKIXPublicKey(pubkey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
i.EncodedPublicKey = base64.RawStdEncoding.EncodeToString(raw)
|
||||||
|
|
||||||
|
return client.write(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NonceProof
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type clientNonceProof struct {
|
||||||
|
OP string `json:"op"`
|
||||||
|
Proof string `json:"proof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *clientNonceProof) send(client *Client) error {
|
||||||
|
n.OP = "nonce_proof"
|
||||||
|
|
||||||
|
// All of the other work was taken care of by the server packet as it knows
|
||||||
|
// the payload.
|
||||||
|
|
||||||
|
return client.write(n)
|
||||||
|
}
|
||||||
211
remoteauth/serverpackets.go
Normal file
211
remoteauth/serverpackets.go
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
package remoteauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type serverPacket interface {
|
||||||
|
process(client *Client) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) processMessages() {
|
||||||
|
type rawPacket struct {
|
||||||
|
OP string `json:"op"`
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, packet, err := c.conn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure) {
|
||||||
|
c.err = err
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := rawPacket{}
|
||||||
|
if err := json.Unmarshal(packet, &raw); err != nil {
|
||||||
|
c.err = err
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var dest interface{}
|
||||||
|
switch raw.OP {
|
||||||
|
case "hello":
|
||||||
|
dest = new(serverHello)
|
||||||
|
case "nonce_proof":
|
||||||
|
dest = new(serverNonceProof)
|
||||||
|
case "pending_remote_init":
|
||||||
|
dest = new(serverPendingRemoteInit)
|
||||||
|
case "pending_finish":
|
||||||
|
dest = new(serverPendingFinish)
|
||||||
|
case "finish":
|
||||||
|
dest = new(serverFinish)
|
||||||
|
case "cancel":
|
||||||
|
dest = new(serverCancel)
|
||||||
|
case "heartbeat_ack":
|
||||||
|
dest = new(serverHeartbeatAck)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(packet, dest); err != nil {
|
||||||
|
c.err = err
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
op := dest.(serverPacket)
|
||||||
|
err = op.process(c)
|
||||||
|
if err != nil {
|
||||||
|
c.err = err
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Hello
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverHello struct {
|
||||||
|
Timeout int `json:"timeout_ms"`
|
||||||
|
HeartbeatInterval int `json:"heartbeat_interval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *serverHello) process(client *Client) error {
|
||||||
|
// Create our heartbeat handler
|
||||||
|
ticker := time.NewTicker(time.Duration(h.HeartbeatInterval) * time.Millisecond)
|
||||||
|
go func() {
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
// case <-client.ctx.Done():
|
||||||
|
// return
|
||||||
|
case <-ticker.C:
|
||||||
|
h := clientHeartbeat{}
|
||||||
|
if err := h.send(client); err != nil {
|
||||||
|
client.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
duration := time.Duration(h.Timeout) * time.Millisecond
|
||||||
|
|
||||||
|
<-time.After(duration)
|
||||||
|
|
||||||
|
client.err = fmt.Errorf("Timed out after %s", duration)
|
||||||
|
client.close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
i := clientInit{}
|
||||||
|
|
||||||
|
return i.send(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NonceProof
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverNonceProof struct {
|
||||||
|
EncryptedNonce string `json:"encrypted_nonce"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *serverNonceProof) process(client *Client) error {
|
||||||
|
plaintext, err := client.decrypt(n.EncryptedNonce)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawProof := sha256.Sum256(plaintext)
|
||||||
|
// The [:] syntax is to return an unsized slice as the sum function returns
|
||||||
|
// one.
|
||||||
|
proof := base64.RawURLEncoding.EncodeToString(rawProof[:])
|
||||||
|
|
||||||
|
c := clientNonceProof{Proof: proof}
|
||||||
|
|
||||||
|
return c.send(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// HeartbeatAck
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverHeartbeatAck struct{}
|
||||||
|
|
||||||
|
func (h *serverHeartbeatAck) process(client *Client) error {
|
||||||
|
client.heartbeats -= 1
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PendingRemoteInit
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverPendingRemoteInit struct {
|
||||||
|
Fingerprint string `json:"fingerprint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *serverPendingRemoteInit) process(client *Client) error {
|
||||||
|
url := "https://discordapp.com/ra/" + p.Fingerprint
|
||||||
|
|
||||||
|
client.qrChan <- url
|
||||||
|
close(client.qrChan)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PendingFinish
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverPendingFinish struct {
|
||||||
|
EncryptedUserPayload string `json:"encrypted_user_payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *serverPendingFinish) process(client *Client) error {
|
||||||
|
plaintext, err := client.decrypt(p.EncryptedUserPayload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.user.update(string(plaintext))
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Finish
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverFinish struct {
|
||||||
|
EncryptedToken string `json:"encrypted_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *serverFinish) process(client *Client) error {
|
||||||
|
plaintext, err := client.decrypt(f.EncryptedToken)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client.user.Token = string(plaintext)
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cancel
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
type serverCancel struct{}
|
||||||
|
|
||||||
|
func (c *serverCancel) process(client *Client) error {
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
29
remoteauth/user.go
Normal file
29
remoteauth/user.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package remoteauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
UserID string
|
||||||
|
Discriminator string
|
||||||
|
AvatarHash string
|
||||||
|
Username string
|
||||||
|
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) update(payload string) error {
|
||||||
|
parts := strings.Split(payload, ":")
|
||||||
|
if len(parts) != 4 {
|
||||||
|
return fmt.Errorf("expected 4 parts but got %d", len(parts))
|
||||||
|
}
|
||||||
|
|
||||||
|
u.UserID = parts[0]
|
||||||
|
u.Discriminator = parts[1]
|
||||||
|
u.AvatarHash = parts[2]
|
||||||
|
u.Username = parts[3]
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user