Skip to content

Commit

Permalink
push: implement PushableNetworkAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Oct 3, 2024
1 parent 969e9a1 commit 321856b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 74 deletions.
5 changes: 0 additions & 5 deletions pkg/connector/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,6 @@ func (m *MetaCookieLogin) SubmitCookies(ctx context.Context, strCookies map[stri
return nil, ErrLoginMissingCookies.AppendMessage(": %v", missingCookies)
}

err := c.GeneratePushKeys()
if err != nil {
return nil, fmt.Errorf("failed to generate push keys: %w", err)
}

log := m.User.Log.With().Str("component", "messagix").Logger()
client := messagix.NewClient(c, log)

Expand Down
60 changes: 60 additions & 0 deletions pkg/connector/push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// mautrix-meta - A Matrix-Facebook Messenger and Instagram DM puppeting bridge.
// Copyright (C) 2024 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

package connector

import (
"context"
"fmt"

"maunium.net/go/mautrix/bridgev2"

"go.mau.fi/mautrix-meta/pkg/messagix"
"go.mau.fi/mautrix-meta/pkg/metaid"
)

var _ bridgev2.PushableNetworkAPI = (*MetaClient)(nil)

var pushCfg = &bridgev2.PushConfig{
Web: &bridgev2.WebPushConfig{VapidKey: "BIBn3E_rWTci8Xn6P9Xj3btShT85Wdtne0LtwNUyRQ5XjFNkuTq9j4MPAVLvAFhXrUU1A9UxyxBA7YIOjqDIDHI"},
}

func (m *MetaClient) GetPushConfigs() *bridgev2.PushConfig {
return pushCfg
}

func (m *MetaClient) RegisterPushNotifications(ctx context.Context, pushType bridgev2.PushType, token string) error {
if pushType != bridgev2.PushTypeWeb {
return fmt.Errorf("unsupported push type %s", pushType)
}
meta := m.UserLogin.Metadata.(*metaid.UserLoginMetadata)
if meta.PushKeys == nil {
meta.GeneratePushKeys()
err := m.UserLogin.Save(ctx)
if err != nil {
return fmt.Errorf("failed to save push key: %w", err)
}
}
keys := messagix.PushKeys{
P256DH: meta.PushKeys.P256DH,
Auth: meta.PushKeys.Auth,
}
if m.Client.Platform.IsMessenger() {
return m.Client.Facebook.RegisterPushNotifications(token, keys)
} else {
return m.Client.Instagram.RegisterPushNotifications(token, keys)
}
}
12 changes: 0 additions & 12 deletions pkg/messagix/cookies/cookies.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ type Cookies struct {
values map[MetaCookieName]string
lock sync.RWMutex

PushKeys *PushKeys
IGWWWClaim string
}

Expand Down Expand Up @@ -91,17 +90,6 @@ func (c *Cookies) GetViewports() (width, height string) {
return pxs[0], pxs[1]
}

func (c *Cookies) GeneratePushKeys() error {
c.lock.RLock()
defer c.lock.RUnlock()
pushKeys, err := generatePushKeys()
if err != nil {
return err
}
c.PushKeys = pushKeys
return nil
}

func (c *Cookies) GetMissingCookieNames() []MetaCookieName {
c.lock.RLock()
defer c.lock.RUnlock()
Expand Down
47 changes: 0 additions & 47 deletions pkg/messagix/cookies/pushkeys.go

This file was deleted.

19 changes: 11 additions & 8 deletions pkg/messagix/facebook.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package messagix

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"strings"

"github.com/google/go-querystring/query"

Expand Down Expand Up @@ -76,9 +76,14 @@ func (fb *FacebookMethods) Login(identifier, password string) (*cookies.Cookies,
return fb.client.cookies, nil
}

func (fb *FacebookMethods) RegisterPushNotifications(endpoint string) error {
type PushKeys struct {
P256DH []byte `json:"p256dh"`
Auth []byte `json:"auth"`
}

func (fb *FacebookMethods) RegisterPushNotifications(endpoint string, keys PushKeys) error {
c := fb.client
jsonKeys, err := json.Marshal(c.cookies.PushKeys.Public)
jsonKeys, err := json.Marshal(&keys)
if err != nil {
c.Logger.Err(err).Msg("failed to encode push keys to json")
return err
Expand Down Expand Up @@ -111,14 +116,12 @@ func (fb *FacebookMethods) RegisterPushNotifications(endpoint string) error {
return fmt.Errorf("bad status code: %d", resp.StatusCode)
}

bodyStr := string(body)
jsonStr := strings.TrimPrefix(bodyStr, "for (;;);")
jsonBytes := []byte(jsonStr)
body = bytes.TrimPrefix(body, antiJSPrefix)

var r pushNotificationsResponse
err = json.Unmarshal(jsonBytes, &r)
err = json.Unmarshal(body, &r)
if err != nil {
c.Logger.Err(err).Str("body", bodyStr).Msg("failed to unmarshal response")
c.Logger.Err(err).Bytes("body", body).Msg("failed to unmarshal response")
return err
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/messagix/instagram.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ func (ig *InstagramMethods) FetchHighlights(highlightIds []string) (*responses.R
return ig.FetchReel(highlightIds, "")
}

func (ig *InstagramMethods) RegisterPushNotifications(endpoint string) error {
func (ig *InstagramMethods) RegisterPushNotifications(endpoint string, keys PushKeys) error {
c := ig.client

jsonKeys, err := json.Marshal(c.cookies.PushKeys.Public)
jsonKeys, err := json.Marshal(&keys)
if err != nil {
c.Logger.Err(err).Msg("failed to encode push keys to json")
return err
Expand Down
20 changes: 20 additions & 0 deletions pkg/metaid/dbmeta.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package metaid

import (
"crypto/ecdh"
"crypto/rand"
"sync/atomic"

"go.mau.fi/util/exerrors"
"go.mau.fi/util/random"
waTypes "go.mau.fi/whatsmeow/types"
"maunium.net/go/mautrix/bridgev2/networkid"

Expand All @@ -23,6 +27,22 @@ type UserLoginMetadata struct {
Platform types.Platform `json:"platform"`
Cookies *cookies.Cookies `json:"cookies"`
WADeviceID uint16 `json:"wa_device_id,omitempty"`
PushKeys *PushKeys `json:"push_keys,omitempty"`
}

type PushKeys struct {
P256DH []byte `json:"p256dh"`
Auth []byte `json:"auth"`
Private []byte `json:"private"`
}

func (m *UserLoginMetadata) GeneratePushKeys() {
privateKey := exerrors.Must(ecdh.P256().GenerateKey(rand.Reader))
m.PushKeys = &PushKeys{
P256DH: privateKey.Public().(*ecdh.PublicKey).Bytes(),
Auth: random.Bytes(16),
Private: privateKey.Bytes(),
}
}

type PortalMetadata struct {
Expand Down

0 comments on commit 321856b

Please sign in to comment.