Explorar el Código

Move whatsapp-ext to go-whatsapp

Tulir Asokan hace 4 años
padre
commit
69dd7f803a

+ 5 - 6
commands.go

@@ -35,7 +35,6 @@ import (
 	"maunium.net/go/mautrix/id"
 
 	"maunium.net/go/mautrix-whatsapp/database"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 type CommandHandler struct {
@@ -737,12 +736,12 @@ const cmdListHelp = `list <contacts|groups> [page] [items per page] - Get a list
 
 func formatContacts(contacts bool, input map[string]whatsapp.Contact) (result []string) {
 	for jid, contact := range input {
-		if strings.HasSuffix(jid, whatsappExt.NewUserSuffix) != contacts {
+		if strings.HasSuffix(jid, whatsapp.NewUserSuffix) != contacts {
 			continue
 		}
 
 		if contacts {
-			result = append(result, fmt.Sprintf("* %s / %s - `%s`", contact.Name, contact.Notify, contact.Jid[:len(contact.Jid)-len(whatsappExt.NewUserSuffix)]))
+			result = append(result, fmt.Sprintf("* %s / %s - `%s`", contact.Name, contact.Notify, contact.Jid[:len(contact.Jid)-len(whatsapp.NewUserSuffix)]))
 		} else {
 			result = append(result, fmt.Sprintf("* %s - `%s`", contact.Name, contact.Jid))
 		}
@@ -818,8 +817,8 @@ func (handler *CommandHandler) CommandOpen(ce *CommandEvent) {
 	user := ce.User
 	jid := ce.Args[0]
 
-	if strings.HasSuffix(jid, whatsappExt.NewUserSuffix) {
-		ce.Reply("That looks like a user JID. Did you mean `pm %s`?", jid[:len(jid)-len(whatsappExt.NewUserSuffix)])
+	if strings.HasSuffix(jid, whatsapp.NewUserSuffix) {
+		ce.Reply("That looks like a user JID. Did you mean `pm %s`?", jid[:len(jid)-len(whatsapp.NewUserSuffix)])
 		return
 	}
 
@@ -865,7 +864,7 @@ func (handler *CommandHandler) CommandPM(ce *CommandEvent) {
 			return
 		}
 	}
-	jid := number + whatsappExt.NewUserSuffix
+	jid := number + whatsapp.NewUserSuffix
 
 	handler.log.Debugln("Importing", jid, "for", user)
 

+ 1 - 3
config/bridge.go

@@ -26,8 +26,6 @@ import (
 
 	"maunium.net/go/mautrix/event"
 	"maunium.net/go/mautrix/id"
-
-	"maunium.net/go/mautrix-whatsapp/types"
 )
 
 type BridgeConfig struct {
@@ -185,7 +183,7 @@ func (bc BridgeConfig) FormatDisplayname(contact whatsapp.Contact) (string, int8
 	return buf.String(), quality
 }
 
-func (bc BridgeConfig) FormatUsername(userID types.WhatsAppID) string {
+func (bc BridgeConfig) FormatUsername(userID whatsapp.JID) string {
 	var buf bytes.Buffer
 	bc.usernameTemplate.Execute(&buf, userID)
 	return buf.String()

+ 8 - 8
database/message.go

@@ -22,11 +22,11 @@ import (
 	"encoding/json"
 	"strings"
 
+	"github.com/Rhymen/go-whatsapp"
 	waProto "github.com/Rhymen/go-whatsapp/binary/proto"
 
 	log "maunium.net/go/maulogger/v2"
 
-	"maunium.net/go/mautrix-whatsapp/types"
 	"maunium.net/go/mautrix/id"
 )
 
@@ -54,18 +54,18 @@ func (mq *MessageQuery) GetAll(chat PortalKey) (messages []*Message) {
 	return
 }
 
-func (mq *MessageQuery) GetByJID(chat PortalKey, jid types.WhatsAppMessageID) *Message {
-	return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
+func (mq *MessageQuery) GetByJID(chat PortalKey, jid whatsapp.MessageID) *Message {
+	return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content "+
 		"FROM message WHERE chat_jid=$1 AND chat_receiver=$2 AND jid=$3", chat.JID, chat.Receiver, jid)
 }
 
 func (mq *MessageQuery) GetByMXID(mxid id.EventID) *Message {
-	return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
+	return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content "+
 		"FROM message WHERE mxid=$1", mxid)
 }
 
 func (mq *MessageQuery) GetLastInChat(chat PortalKey) *Message {
-	msg := mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
+	msg := mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content "+
 		"FROM message WHERE chat_jid=$1 AND chat_receiver=$2 ORDER BY timestamp DESC LIMIT 1", chat.JID, chat.Receiver)
 	if msg == nil || msg.Timestamp == 0 {
 		// Old db, we don't know what the last message is.
@@ -87,9 +87,9 @@ type Message struct {
 	log log.Logger
 
 	Chat      PortalKey
-	JID       types.WhatsAppMessageID
+	JID       whatsapp.MessageID
 	MXID      id.EventID
-	Sender    types.WhatsAppID
+	Sender    whatsapp.JID
 	Timestamp uint64
 	Content   *waProto.Message
 }
@@ -134,7 +134,7 @@ func (msg *Message) encodeBinaryContent() []byte {
 }
 
 func (msg *Message) Insert() {
-	_, err := msg.db.Exec("INSERT INTO message (chat_jid, chat_receiver, jid, mxid, sender, timestamp, content) " +
+	_, err := msg.db.Exec("INSERT INTO message (chat_jid, chat_receiver, jid, mxid, sender, timestamp, content) "+
 		"VALUES ($1, $2, $3, $4, $5, $6, $7)",
 		msg.Chat.JID, msg.Chat.Receiver, msg.JID, msg.MXID, msg.Sender, msg.Timestamp, msg.encodeBinaryContent())
 	if err != nil {

+ 8 - 8
database/portal.go

@@ -22,24 +22,24 @@ import (
 
 	log "maunium.net/go/maulogger/v2"
 
-	"maunium.net/go/mautrix/id"
+	"github.com/Rhymen/go-whatsapp"
 
-	"maunium.net/go/mautrix-whatsapp/types"
+	"maunium.net/go/mautrix/id"
 )
 
 type PortalKey struct {
-	JID      types.WhatsAppID
-	Receiver types.WhatsAppID
+	JID      whatsapp.JID
+	Receiver whatsapp.JID
 }
 
-func GroupPortalKey(jid types.WhatsAppID) PortalKey {
+func GroupPortalKey(jid whatsapp.JID) PortalKey {
 	return PortalKey{
 		JID:      jid,
 		Receiver: jid,
 	}
 }
 
-func NewPortalKey(jid, receiver types.WhatsAppID) PortalKey {
+func NewPortalKey(jid, receiver whatsapp.JID) PortalKey {
 	if strings.HasSuffix(jid, "@g.us") {
 		receiver = jid
 	}
@@ -80,11 +80,11 @@ func (pq *PortalQuery) GetByMXID(mxid id.RoomID) *Portal {
 	return pq.get("SELECT * FROM portal WHERE mxid=$1", mxid)
 }
 
-func (pq *PortalQuery) GetAllByJID(jid types.WhatsAppID) []*Portal {
+func (pq *PortalQuery) GetAllByJID(jid whatsapp.JID) []*Portal {
 	return pq.getAll("SELECT * FROM portal WHERE jid=$1", jid)
 }
 
-func (pq *PortalQuery) FindPrivateChats(receiver types.WhatsAppID) []*Portal {
+func (pq *PortalQuery) FindPrivateChats(receiver whatsapp.JID) []*Portal {
 	return pq.getAll("SELECT * FROM portal WHERE receiver=$1 AND jid LIKE '%@s.whatsapp.net'", receiver)
 }
 

+ 4 - 4
database/puppet.go

@@ -21,9 +21,9 @@ import (
 
 	log "maunium.net/go/maulogger/v2"
 
-	"maunium.net/go/mautrix/id"
+	"github.com/Rhymen/go-whatsapp"
 
-	"maunium.net/go/mautrix-whatsapp/types"
+	"maunium.net/go/mautrix/id"
 )
 
 type PuppetQuery struct {
@@ -53,7 +53,7 @@ func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
 	return
 }
 
-func (pq *PuppetQuery) Get(jid types.WhatsAppID) *Puppet {
+func (pq *PuppetQuery) Get(jid whatsapp.JID) *Puppet {
 	row := pq.db.QueryRow("SELECT jid, avatar, avatar_url, displayname, name_quality, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE jid=$1", jid)
 	if row == nil {
 		return nil
@@ -85,7 +85,7 @@ type Puppet struct {
 	db  *Database
 	log log.Logger
 
-	JID         types.WhatsAppID
+	JID         whatsapp.JID
 	Avatar      string
 	AvatarURL   id.ContentURI
 	Displayname string

+ 5 - 7
database/user.go

@@ -26,8 +26,6 @@ import (
 
 	log "maunium.net/go/maulogger/v2"
 
-	"maunium.net/go/mautrix-whatsapp/types"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 	"maunium.net/go/mautrix/id"
 )
 
@@ -63,7 +61,7 @@ func (uq *UserQuery) GetByMXID(userID id.UserID) *User {
 	return uq.New().Scan(row)
 }
 
-func (uq *UserQuery) GetByJID(userID types.WhatsAppID) *User {
+func (uq *UserQuery) GetByJID(userID whatsapp.JID) *User {
 	row := uq.db.QueryRow(`SELECT mxid, jid, management_room, last_connection, client_id, client_token, server_token, enc_key, mac_key FROM "user" WHERE jid=$1`, stripSuffix(userID))
 	if row == nil {
 		return nil
@@ -76,7 +74,7 @@ type User struct {
 	log log.Logger
 
 	MXID           id.UserID
-	JID            types.WhatsAppID
+	JID            whatsapp.JID
 	ManagementRoom id.RoomID
 	Session        *whatsapp.Session
 	LastConnection uint64
@@ -93,14 +91,14 @@ func (user *User) Scan(row Scannable) *User {
 		return nil
 	}
 	if len(jid.String) > 0 && len(clientID.String) > 0 {
-		user.JID = jid.String + whatsappExt.NewUserSuffix
+		user.JID = jid.String + whatsapp.NewUserSuffix
 		user.Session = &whatsapp.Session{
 			ClientId:    clientID.String,
 			ClientToken: clientToken.String,
 			ServerToken: serverToken.String,
 			EncKey:      encKey,
 			MacKey:      macKey,
-			Wid:         jid.String + whatsappExt.OldUserSuffix,
+			Wid:         jid.String + whatsapp.OldUserSuffix,
 		}
 	} else {
 		user.Session = nil
@@ -108,7 +106,7 @@ func (user *User) Scan(row Scannable) *User {
 	return user
 }
 
-func stripSuffix(jid types.WhatsAppID) string {
+func stripSuffix(jid whatsapp.JID) string {
 	if len(jid) == 0 {
 		return jid
 	}

+ 9 - 10
formatting.go

@@ -22,12 +22,11 @@ import (
 	"regexp"
 	"strings"
 
+	"github.com/Rhymen/go-whatsapp"
+
 	"maunium.net/go/mautrix/event"
 	"maunium.net/go/mautrix/format"
 	"maunium.net/go/mautrix/id"
-
-	"maunium.net/go/mautrix-whatsapp/types"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 var italicRegex = regexp.MustCompile("([\\s>~*]|^)_(.+?)_([^a-zA-Z\\d]|$)")
@@ -58,9 +57,9 @@ func NewFormatter(bridge *Bridge) *Formatter {
 				if mxid[0] == '@' {
 					puppet := bridge.GetPuppetByMXID(id.UserID(mxid))
 					if puppet != nil {
-						jids, ok := ctx[mentionedJIDsContextKey].([]types.WhatsAppID)
+						jids, ok := ctx[mentionedJIDsContextKey].([]whatsapp.JID)
 						if !ok {
-							ctx[mentionedJIDsContextKey] = []types.WhatsAppID{puppet.JID}
+							ctx[mentionedJIDsContextKey] = []whatsapp.JID{puppet.JID}
 						} else {
 							ctx[mentionedJIDsContextKey] = append(jids, puppet.JID)
 						}
@@ -105,7 +104,7 @@ func NewFormatter(bridge *Bridge) *Formatter {
 	return formatter
 }
 
-func (formatter *Formatter) getMatrixInfoByJID(jid types.WhatsAppID) (mxid id.UserID, displayname string) {
+func (formatter *Formatter) getMatrixInfoByJID(jid whatsapp.JID) (mxid id.UserID, displayname string) {
 	if user := formatter.bridge.GetUserByJID(jid); user != nil {
 		mxid = user.MXID
 		displayname = string(user.MXID)
@@ -116,7 +115,7 @@ func (formatter *Formatter) getMatrixInfoByJID(jid types.WhatsAppID) (mxid id.Us
 	return
 }
 
-func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, mentionedJIDs []types.WhatsAppID) {
+func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, mentionedJIDs []whatsapp.JID) {
 	output := html.EscapeString(content.Body)
 	for regex, replacement := range formatter.waReplString {
 		output = regex.ReplaceAllString(output, replacement)
@@ -126,7 +125,7 @@ func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, me
 	}
 	for _, jid := range mentionedJIDs {
 		mxid, displayname := formatter.getMatrixInfoByJID(jid)
-		number := "@" + strings.Replace(jid, whatsappExt.NewUserSuffix, "", 1)
+		number := "@" + strings.Replace(jid, whatsapp.NewUserSuffix, "", 1)
 		output = strings.Replace(output, number, fmt.Sprintf(`<a href="https://matrix.to/#/%s">%s</a>`, mxid, displayname), -1)
 		content.Body = strings.Replace(content.Body, number, displayname, -1)
 	}
@@ -140,9 +139,9 @@ func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, me
 	}
 }
 
-func (formatter *Formatter) ParseMatrix(html string) (string, []types.WhatsAppID) {
+func (formatter *Formatter) ParseMatrix(html string) (string, []whatsapp.JID) {
 	ctx := make(format.Context)
 	result := formatter.matrixHTMLParser.Parse(html, ctx)
-	mentionedJIDs, _ := ctx[mentionedJIDsContextKey].([]types.WhatsAppID)
+	mentionedJIDs, _ := ctx[mentionedJIDsContextKey].([]whatsapp.JID)
 	return result, mentionedJIDs
 }

+ 0 - 2
helm/mautrix-whatsapp/.editorconfig

@@ -1,2 +0,0 @@
-[*.{yaml,yml}]
-indent_size = 2

+ 0 - 2
helm/mautrix-whatsapp/.gitignore

@@ -1,2 +0,0 @@
-charts/*
-!*.yaml

+ 0 - 22
helm/mautrix-whatsapp/.helmignore

@@ -1,22 +0,0 @@
-# Patterns to ignore when building packages.
-# This supports shell glob matching, relative path matching, and
-# negation (prefixed with !). Only one pattern per line.
-.DS_Store
-# Common VCS dirs
-.git/
-.gitignore
-.bzr/
-.bzrignore
-.hg/
-.hgignore
-.svn/
-# Common backup files
-*.swp
-*.bak
-*.tmp
-*~
-# Various IDEs
-.project
-.idea/
-*.tmproj
-.vscode/

+ 0 - 14
helm/mautrix-whatsapp/Chart.yaml

@@ -1,14 +0,0 @@
-apiVersion: v1
-name: mautrix-whatsapp
-version: 0.1.0
-appVersion: "0.1.0"
-description: A Matrix-Whatsapp puppeting bridge.
-keywords:
-  - matrix
-  - bridge
-  - whatsapp
-maintainers:
-  - name: Tulir Asokan
-    email: tulir@maunium.net
-sources:
-  - https://github.com/tulir/mautrix-whatsapp

+ 0 - 6
helm/mautrix-whatsapp/requirements.lock

@@ -1,6 +0,0 @@
-dependencies:
-- name: postgresql
-  repository: https://kubernetes-charts.storage.googleapis.com/
-  version: 6.5.0
-digest: sha256:85139e9d4207e49c11c5f84d7920d0135cffd3d427f3f3638d4e51258990de2a
-generated: "2019-10-23T22:11:37.005827507+03:00"

+ 0 - 5
helm/mautrix-whatsapp/requirements.yaml

@@ -1,5 +0,0 @@
-dependencies:
-  - name: postgresql
-    version: 6.5.0
-    repository: https://kubernetes-charts.storage.googleapis.com/
-    condition: postgresql.enabled

+ 0 - 12
helm/mautrix-whatsapp/templates/NOTES.txt

@@ -1,12 +0,0 @@
-Your registration file is below. Save it into a YAML file and give the path to that file to synapse:
-
-id: {{ .Values.appservice.id }}
-as_token: {{ .Values.appservice.asToken }}
-hs_token: {{ .Values.appservice.hsToken }}
-namespaces:
-    users:
-        - exclusive: true
-          regex: "@{{ .Values.bridge.username_template | replace "{{.}}" ".+"}}:{{ .Values.homeserver.domain }}"
-url: {{ .Values.appservice.address }}
-sender_localpart: {{ .Values.appservice.botUsername }}
-rate_limited: false

+ 0 - 55
helm/mautrix-whatsapp/templates/_helpers.tpl

@@ -1,55 +0,0 @@
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "mautrix-whatsapp.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
-{{- end -}}
-
-{{/*
-Create a default fully qualified app name.
-We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
-If release name contains chart name it will be used as a full name.
-*/}}
-{{- define "mautrix-whatsapp.fullname" -}}
-{{- if .Values.fullnameOverride -}}
-{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
-{{- else -}}
-{{- $name := default .Chart.Name .Values.nameOverride -}}
-{{- if contains $name .Release.Name -}}
-{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
-{{- else -}}
-{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
-{{- end -}}
-{{- end -}}
-{{- end -}}
-
-{{/*
-Create chart name and version as used by the chart label.
-*/}}
-{{- define "mautrix-whatsapp.chart" -}}
-{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
-{{- end -}}
-
-{{/*
-Common labels
-*/}}
-{{- define "mautrix-whatsapp.labels" -}}
-app.kubernetes.io/name: {{ include "mautrix-whatsapp.name" . }}
-helm.sh/chart: {{ include "mautrix-whatsapp.chart" . }}
-app.kubernetes.io/instance: {{ .Release.Name }}
-{{- if .Chart.AppVersion }}
-app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
-{{- end }}
-app.kubernetes.io/managed-by: {{ .Release.Service }}
-{{- end -}}
-
-{{/*
-Create the name of the service account to use
-*/}}
-{{- define "mautrix-whatsapp.serviceAccountName" -}}
-{{- if .Values.serviceAccount.create -}}
-    {{ default (include "mautrix-whatsapp.fullname" .) .Values.serviceAccount.name }}
-{{- else -}}
-    {{ default "default" .Values.serviceAccount.name }}
-{{- end -}}
-{{- end -}}

+ 0 - 45
helm/mautrix-whatsapp/templates/configmap.yaml

@@ -1,45 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
-  name: {{ template "mautrix-whatsapp.fullname" . }}
-  labels:
-    app.kubernetes.io/managed-by: {{ .Release.Service }}
-    app.kubernetes.io/instance: {{ .Release.Name }}
-    helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
-    app.kubernetes.io/name: {{ template "mautrix-whatsapp.name" . }}
-data:
-  config.yaml: |
-    homeserver:
-      address: {{ .Values.homeserver.address }}
-      domain: {{ .Values.homeserver.domain }}
-
-    appservice:
-      address: http://{{ include "mautrix-whatsapp.fullname" . }}:{{ .Values.service.port }}
-
-      hostname: 0.0.0.0
-      port: {{ .Values.service.port }}
-
-      {{- if .Values.postgresql.enabled }}
-      database:
-        type: postgres
-        uri: "postgres://postgres:{{ .Values.postgresql.postgresqlPassword }}@{{ .Release.Name }}-postgresql/{{ .Values.postgresql.postgresqlDatabase }}?sslmode=disable"
-      {{- else }}
-      database:
-        {{- toYaml .Values.appservice.database | nindent 8 }}
-      {{- end }}
-
-      id: {{ .Values.appservice.id }}
-      bot:
-        username: {{ .Values.appservice.botUsername }}
-        displayname: {{ .Values.appservice.botDisplayname }}
-        avatar:  {{ .Values.appservice.botAvatar }}
-
-      as_token: {{ .Values.appservice.asToken }}
-      hs_token: {{ .Values.appservice.hsToken }}
-
-    bridge:
-      {{- toYaml .Values.bridge | nindent 6 }}
-
-    logging:
-      {{- toYaml .Values.logging | nindent 6 }}
-  registration.yaml: ""

+ 0 - 69
helm/mautrix-whatsapp/templates/deployment.yaml

@@ -1,69 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: {{ include "mautrix-whatsapp.fullname" . }}
-  labels:
-    {{- include "mautrix-whatsapp.labels" . | nindent 4 }}
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      app.kubernetes.io/name: {{ include "mautrix-whatsapp.name" . }}
-      app.kubernetes.io/instance: {{ .Release.Name }}
-  template:
-    {{- if .Values.podAnnotations }}
-    annotations:
-      {{- toYaml .Values.podAnnotations | nindent 6 }}
-    {{- end }}
-    metadata:
-      labels:
-        app.kubernetes.io/name: {{ include "mautrix-whatsapp.name" . }}
-        app.kubernetes.io/instance: {{ .Release.Name }}
-    spec:
-      serviceAccountName: {{ template "mautrix-whatsapp.serviceAccountName" . }}
-      containers:
-        - name: {{ .Chart.Name }}
-          securityContext:
-            {{- toYaml .Values.securityContext | nindent 12 }}
-          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
-          imagePullPolicy: {{ .Values.image.pullPolicy }}
-          volumeMounts:
-            - mountPath: /data
-              name: config-volume
-          ports:
-            - name: http
-              containerPort: {{ .Values.service.port }}
-              protocol: TCP
-#          livenessProbe:
-#            httpGet:
-#              path: /_matrix/mau/live
-#              port: http
-#            initialDelaySeconds: 60
-#            periodSeconds: 5
-#          readinessProbe:
-#            httpGet:
-#              path: /_matrix/mau/ready
-#              port: http
-#            initialDelaySeconds: 60
-#            periodSeconds: 5
-          resources:
-            {{- toYaml .Values.resources | nindent 12 }}
-      volumes:
-        - name: config-volume
-          configMap:
-            name: {{ template "mautrix-whatsapp.fullname" . }}
-
-      securityContext:
-        {{- toYaml .Values.podSecurityContext | nindent 8 }}
-      {{- with .Values.nodeSelector }}
-      nodeSelector:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      {{- with .Values.affinity }}
-      affinity:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      {{- with .Values.tolerations }}
-      tolerations:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}

+ 0 - 16
helm/mautrix-whatsapp/templates/service.yaml

@@ -1,16 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: {{ include "mautrix-whatsapp.fullname" . }}
-  labels:
-{{ include "mautrix-whatsapp.labels" . | indent 4 }}
-spec:
-  type: {{ .Values.service.type }}
-  ports:
-    - port: {{ .Values.service.port }}
-      targetPort: http
-      protocol: TCP
-      name: http
-  selector:
-    app.kubernetes.io/name: {{ include "mautrix-whatsapp.name" . }}
-    app.kubernetes.io/instance: {{ .Release.Name }}

+ 0 - 8
helm/mautrix-whatsapp/templates/serviceaccount.yaml

@@ -1,8 +0,0 @@
-{{- if .Values.serviceAccount.create -}}
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: {{ template "mautrix-whatsapp.serviceAccountName" . }}
-  labels:
-{{ include "mautrix-whatsapp.labels" . | indent 4 }}
-{{- end -}}

+ 0 - 137
helm/mautrix-whatsapp/values.yaml

@@ -1,137 +0,0 @@
-image:
-  repository: dock.mau.dev/tulir/mautrix-whatsapp
-  tag: latest
-  pullPolicy: IfNotPresent
-
-nameOverride: ""
-fullnameOverride: ""
-
-serviceAccount:
-  # Specifies whether a service account should be created
-  create: true
-  # The name of the service account to use.
-  # If not set and create is true, a name is generated using the fullname template
-  name:
-
-service:
-  type: ClusterIP
-  port: 29318
-
-resources: {}
-  # limits:
-  #   cpu: 100m
-  #   memory: 128Mi
-  # requests:
-  #   cpu: 100m
-  #   memory: 128Mi
-
-nodeSelector: {}
-
-tolerations: []
-
-affinity: {}
-
-# Postgres pod configs
-postgresql:
-  enabled: true
-  postgresqlDatabase: mxwa
-  postgresqlPassword: SET TO RANDOM STRING
-  persistence:
-    size: 2Gi
-  resources:
-    requests:
-      memory: 256Mi
-      cpu: 100m
-
-# Homeserver details
-homeserver:
-  # The address that this appservice can use to connect to the homeserver.
-  address: https://example.com
-  # The domain of the homeserver (for MXIDs, etc).
-  domain: example.com
-
-# Application service host/registration related details
-# Changing these values requires regeneration of the registration.
-appservice:
-  id: whatsapp
-  botUsername: whatsappbot
-  # Display name and avatar for bot. Set to "remove" to remove display name/avatar, leave empty
-  # to leave display name/avatar as-is.
-  botDisplayname: WhatsApp bridge bot
-  botAvatar: mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr
-
-  # Authentication tokens for AS <-> HS communication.
-  asToken: SET TO RANDOM STRING
-  hsToken: SET TO RANDOM STRING
-
-# The keys below can be used to override the configs in the base config:
-# https://github.com/tulir/mautrix-whatsapp/blob/master/example-config.yaml
-# Note that the "appservice" and "homeserver" sections are above and slightly different than the base.
-
-# Bridge config
-bridge:
-  # Localpart template of MXIDs for WhatsApp users.
-  # {{.}} is replaced with the phone number of the WhatsApp user.
-  username_template: whatsapp_{{.}}
-
-  # Number of chats to sync for new users.
-  initial_chat_sync_count: 10
-  # Number of old messages to fill when creating new portal rooms.
-  initial_history_fill_count: 20
-  # Maximum number of chats to sync when recovering from downtime.
-  # Set to -1 to sync all new chats during downtime.
-  recovery_chat_sync_limit: -1
-  # Whether or not to sync history when recovering from downtime.
-  recovery_history_backfill: true
-  # Maximum number of seconds since last message in chat to skip
-  # syncing the chat in any case. This setting will take priority
-  # over both recovery_chat_sync_limit and initial_chat_sync_count.
-  # Default is 3 days = 259200 seconds
-  sync_max_chat_age: 259200
-
-  # Whether or not to explicitly set the avatar and room name for private
-  # chat portal rooms. This can be useful if the previous field works fine,
-  # but causes room avatar/name bugs.
-  private_chat_portal_meta: true
-
-  # Allow invite permission for user. User can invite any bots to room with whatsapp
-  # users (private chat and groups)
-  allow_user_invite: true
-
-  # Permissions for using the bridge.
-  # Permitted values:
-  # relaybot - Talk through the relaybot (if enabled), no access otherwise
-  #     user - Access to use the bridge to chat with a WhatsApp account.
-  #    admin - User level and some additional administration tools
-  # Permitted keys:
-  #        * - All Matrix users
-  #   domain - All users on that homeserver
-  #     mxid - Specific user
-  permissions:
-    "*": relaybot
-    "example.com": user
-    "@admin:example.com": admin
-
-  relaybot:
-    # Whether or not relaybot support is enabled.
-    enabled: false
-    # The management room for the bot. This is where all status notifications are posted and
-    # in this room, you can use `!wa <command>` instead of `!wa relaybot <command>`. Omitting
-    # the command prefix completely like in user management rooms is not possible.
-    management: !foo:example.com
-    # List of users to invite to all created rooms that include the relaybot.
-    invites: []
-    # The formats to use when sending messages to WhatsApp via the relaybot.
-    message_formats:
-      m.text: "<b>{{ .Sender.Displayname }}</b>: {{ .Message }}"
-      m.notice: "<b>{{ .Sender.Displayname }}</b>: {{ .Message }}"
-      m.emote: "* <b>{{ .Sender.Displayname }}</b> {{ .Message }}"
-      m.file: "<b>{{ .Sender.Displayname }}</b> sent a file"
-      m.image: "<b>{{ .Sender.Displayname }}</b> sent an image"
-      m.audio: "<b>{{ .Sender.Displayname }}</b> sent an audio file"
-      m.video: "<b>{{ .Sender.Displayname }}</b> sent a video"
-      m.location: "<b>{{ .Sender.Displayname }}</b> sent a location"
-
-logging:
-  timestamp_format: Jan _2, 2006 15:04:05
-  print_level: debug

+ 6 - 5
main.go

@@ -25,6 +25,8 @@ import (
 	"syscall"
 	"time"
 
+	"github.com/Rhymen/go-whatsapp"
+
 	flag "maunium.net/go/mauflag"
 	log "maunium.net/go/maulogger/v2"
 
@@ -36,7 +38,6 @@ import (
 	"maunium.net/go/mautrix-whatsapp/config"
 	"maunium.net/go/mautrix-whatsapp/database"
 	"maunium.net/go/mautrix-whatsapp/database/upgrades"
-	"maunium.net/go/mautrix-whatsapp/types"
 )
 
 var (
@@ -137,14 +138,14 @@ type Bridge struct {
 	Metrics        *MetricsHandler
 
 	usersByMXID         map[id.UserID]*User
-	usersByJID          map[types.WhatsAppID]*User
+	usersByJID          map[whatsapp.JID]*User
 	usersLock           sync.Mutex
 	managementRooms     map[id.RoomID]*User
 	managementRoomsLock sync.Mutex
 	portalsByMXID       map[id.RoomID]*Portal
 	portalsByJID        map[database.PortalKey]*Portal
 	portalsLock         sync.Mutex
-	puppets             map[types.WhatsAppID]*Puppet
+	puppets             map[whatsapp.JID]*Puppet
 	puppetsByCustomMXID map[id.UserID]*Puppet
 	puppetsLock         sync.Mutex
 }
@@ -163,11 +164,11 @@ type Crypto interface {
 func NewBridge() *Bridge {
 	bridge := &Bridge{
 		usersByMXID:         make(map[id.UserID]*User),
-		usersByJID:          make(map[types.WhatsAppID]*User),
+		usersByJID:          make(map[whatsapp.JID]*User),
 		managementRooms:     make(map[id.RoomID]*User),
 		portalsByMXID:       make(map[id.RoomID]*Portal),
 		portalsByJID:        make(map[database.PortalKey]*Portal),
-		puppets:             make(map[types.WhatsAppID]*Puppet),
+		puppets:             make(map[whatsapp.JID]*Puppet),
 		puppetsByCustomMXID: make(map[id.UserID]*Puppet),
 	}
 

+ 4 - 0
matrix.go

@@ -254,6 +254,10 @@ func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
 		return
 	}
 
+	if mx.shouldIgnoreEvent(evt) {
+		return
+	}
+
 	user := mx.bridge.GetUserByMXID(evt.Sender)
 	if user == nil || !user.Whitelisted || !user.IsConnected() {
 		return

+ 11 - 10
metrics.go

@@ -27,11 +27,12 @@ import (
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	log "maunium.net/go/maulogger/v2"
 
+	"github.com/Rhymen/go-whatsapp"
+
 	"maunium.net/go/mautrix/event"
 	"maunium.net/go/mautrix/id"
 
 	"maunium.net/go/mautrix-whatsapp/database"
-	"maunium.net/go/mautrix-whatsapp/types"
 )
 
 type MetricsHandler struct {
@@ -56,11 +57,11 @@ type MetricsHandler struct {
 	unencryptedPrivateCount prometheus.Gauge
 
 	connected       prometheus.Gauge
-	connectedState  map[types.WhatsAppID]bool
+	connectedState  map[whatsapp.JID]bool
 	loggedIn        prometheus.Gauge
-	loggedInState   map[types.WhatsAppID]bool
+	loggedInState   map[whatsapp.JID]bool
 	syncLocked      prometheus.Gauge
-	syncLockedState map[types.WhatsAppID]bool
+	syncLockedState map[whatsapp.JID]bool
 	bufferLength    *prometheus.GaugeVec
 }
 
@@ -109,17 +110,17 @@ func NewMetricsHandler(address string, log log.Logger, db *database.Database) *M
 			Name: "bridge_logged_in",
 			Help: "Users logged into the bridge",
 		}),
-		loggedInState: make(map[types.WhatsAppID]bool),
+		loggedInState: make(map[whatsapp.JID]bool),
 		connected: promauto.NewGauge(prometheus.GaugeOpts{
 			Name: "bridge_connected",
 			Help: "Bridge users connected to WhatsApp",
 		}),
-		connectedState: make(map[types.WhatsAppID]bool),
+		connectedState: make(map[whatsapp.JID]bool),
 		syncLocked: promauto.NewGauge(prometheus.GaugeOpts{
 			Name: "bridge_sync_locked",
 			Help: "Bridge users locked in post-login sync",
 		}),
-		syncLockedState: make(map[types.WhatsAppID]bool),
+		syncLockedState: make(map[whatsapp.JID]bool),
 		bufferLength: promauto.NewGaugeVec(prometheus.GaugeOpts{
 			Name: "bridge_buffer_size",
 			Help: "Number of messages in buffer",
@@ -149,7 +150,7 @@ func (mh *MetricsHandler) TrackDisconnection(userID id.UserID) {
 	mh.disconnections.With(prometheus.Labels{"user_id": string(userID)}).Inc()
 }
 
-func (mh *MetricsHandler) TrackLoginState(jid types.WhatsAppID, loggedIn bool) {
+func (mh *MetricsHandler) TrackLoginState(jid whatsapp.JID, loggedIn bool) {
 	if !mh.running {
 		return
 	}
@@ -164,7 +165,7 @@ func (mh *MetricsHandler) TrackLoginState(jid types.WhatsAppID, loggedIn bool) {
 	}
 }
 
-func (mh *MetricsHandler) TrackConnectionState(jid types.WhatsAppID, connected bool) {
+func (mh *MetricsHandler) TrackConnectionState(jid whatsapp.JID, connected bool) {
 	if !mh.running {
 		return
 	}
@@ -179,7 +180,7 @@ func (mh *MetricsHandler) TrackConnectionState(jid types.WhatsAppID, connected b
 	}
 }
 
-func (mh *MetricsHandler) TrackSyncLock(jid types.WhatsAppID, locked bool) {
+func (mh *MetricsHandler) TrackSyncLock(jid whatsapp.JID, locked bool) {
 	if !mh.running {
 		return
 	}

+ 18 - 22
portal.go

@@ -40,23 +40,19 @@ import (
 	"sync"
 	"time"
 
-	log "maunium.net/go/maulogger/v2"
-
-	"maunium.net/go/mautrix/crypto/attachment"
-
 	"github.com/Rhymen/go-whatsapp"
 	waProto "github.com/Rhymen/go-whatsapp/binary/proto"
 
+	log "maunium.net/go/maulogger/v2"
 	"maunium.net/go/mautrix"
 	"maunium.net/go/mautrix/appservice"
+	"maunium.net/go/mautrix/crypto/attachment"
 	"maunium.net/go/mautrix/event"
 	"maunium.net/go/mautrix/format"
 	"maunium.net/go/mautrix/id"
 	"maunium.net/go/mautrix/pushrules"
 
 	"maunium.net/go/mautrix-whatsapp/database"
-	"maunium.net/go/mautrix-whatsapp/types"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 func (bridge *Bridge) GetPortalByMXID(mxid id.RoomID) *Portal {
@@ -83,7 +79,7 @@ func (bridge *Bridge) GetAllPortals() []*Portal {
 	return bridge.dbPortalsToPortals(bridge.DB.Portal.GetAll())
 }
 
-func (bridge *Bridge) GetAllPortalsByJID(jid types.WhatsAppID) []*Portal {
+func (bridge *Bridge) GetAllPortalsByJID(jid whatsapp.JID) []*Portal {
 	return bridge.dbPortalsToPortals(bridge.DB.Portal.GetAllByJID(jid))
 }
 
@@ -131,7 +127,7 @@ func (bridge *Bridge) NewManualPortal(key database.PortalKey) *Portal {
 		bridge: bridge,
 		log:    bridge.Log.Sub(fmt.Sprintf("Portal/%s", key)),
 
-		recentlyHandled: [recentlyHandledLength]types.WhatsAppMessageID{},
+		recentlyHandled: [recentlyHandledLength]whatsapp.MessageID{},
 
 		messages: make(chan PortalMessage, bridge.Config.Bridge.PortalMessageBuffer),
 	}
@@ -146,7 +142,7 @@ func (bridge *Bridge) NewPortal(dbPortal *database.Portal) *Portal {
 		bridge: bridge,
 		log:    bridge.Log.Sub(fmt.Sprintf("Portal/%s", dbPortal.Key)),
 
-		recentlyHandled: [recentlyHandledLength]types.WhatsAppMessageID{},
+		recentlyHandled: [recentlyHandledLength]whatsapp.MessageID{},
 
 		messages: make(chan PortalMessage, bridge.Config.Bridge.PortalMessageBuffer),
 	}
@@ -171,7 +167,7 @@ type Portal struct {
 
 	roomCreateLock sync.Mutex
 
-	recentlyHandled      [recentlyHandledLength]types.WhatsAppMessageID
+	recentlyHandled      [recentlyHandledLength]whatsapp.MessageID
 	recentlyHandledLock  sync.Mutex
 	recentlyHandledIndex uint8
 
@@ -256,7 +252,7 @@ func (portal *Portal) handleMessage(msg PortalMessage, isBackfill bool) {
 		portal.HandleLocationMessage(msg.source, data)
 	case whatsapp.StubMessage:
 		portal.HandleStubMessage(msg.source, data, isBackfill)
-	case whatsappExt.MessageRevocation:
+	case whatsapp.MessageRevocation:
 		portal.HandleMessageRevoke(msg.source, data)
 	case FakeMessage:
 		portal.HandleFakeMessage(msg.source, data)
@@ -265,7 +261,7 @@ func (portal *Portal) handleMessage(msg PortalMessage, isBackfill bool) {
 	}
 }
 
-func (portal *Portal) isRecentlyHandled(id types.WhatsAppMessageID) bool {
+func (portal *Portal) isRecentlyHandled(id whatsapp.MessageID) bool {
 	start := portal.recentlyHandledIndex
 	for i := start; i != start; i = (i - 1) % recentlyHandledLength {
 		if portal.recentlyHandled[i] == id {
@@ -275,7 +271,7 @@ func (portal *Portal) isRecentlyHandled(id types.WhatsAppMessageID) bool {
 	return false
 }
 
-func (portal *Portal) isDuplicate(id types.WhatsAppMessageID) bool {
+func (portal *Portal) isDuplicate(id whatsapp.MessageID) bool {
 	msg := portal.bridge.DB.Message.GetByJID(portal.Key, id)
 	if msg != nil {
 		return true
@@ -355,7 +351,7 @@ func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageIn
 	portal.log.Debugln("Handled message", message.GetKey().GetId(), "->", mxid)
 }
 
-func (portal *Portal) SyncParticipants(metadata *whatsappExt.GroupInfo) {
+func (portal *Portal) SyncParticipants(metadata *whatsapp.GroupInfo) {
 	changed := false
 	levels, err := portal.MainIntent().PowerLevels(portal.MXID)
 	if err != nil {
@@ -413,7 +409,7 @@ func (portal *Portal) SyncParticipants(metadata *whatsappExt.GroupInfo) {
 	}
 }
 
-func (portal *Portal) UpdateAvatar(user *User, avatar *whatsappExt.ProfilePicInfo, updateInfo bool) bool {
+func (portal *Portal) UpdateAvatar(user *User, avatar *whatsapp.ProfilePicInfo, updateInfo bool) bool {
 	if avatar == nil || (avatar.Status == 0 && avatar.Tag != "remove" && len(avatar.URL) == 0) {
 		var err error
 		avatar, err = user.Conn.GetProfilePicThumb(portal.Key.JID)
@@ -464,7 +460,7 @@ func (portal *Portal) UpdateAvatar(user *User, avatar *whatsappExt.ProfilePicInf
 	return true
 }
 
-func (portal *Portal) UpdateName(name string, setBy types.WhatsAppID, intent *appservice.IntentAPI, updateInfo bool) bool {
+func (portal *Portal) UpdateName(name string, setBy whatsapp.JID, intent *appservice.IntentAPI, updateInfo bool) bool {
 	if portal.Name != name {
 		portal.log.Debugfln("Updating name %s -> %s", portal.Name, name)
 		portal.Name = name
@@ -488,7 +484,7 @@ func (portal *Portal) UpdateName(name string, setBy types.WhatsAppID, intent *ap
 	return false
 }
 
-func (portal *Portal) UpdateTopic(topic string, setBy types.WhatsAppID, intent *appservice.IntentAPI, updateInfo bool) bool {
+func (portal *Portal) UpdateTopic(topic string, setBy whatsapp.JID, intent *appservice.IntentAPI, updateInfo bool) bool {
 	if portal.Topic != topic {
 		portal.log.Debugfln("Updating topic %s -> %s", portal.Topic, topic)
 		portal.Topic = topic
@@ -974,7 +970,7 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 
 	portal.log.Infoln("Creating Matrix room. Info source:", user.MXID)
 
-	var metadata *whatsappExt.GroupInfo
+	var metadata *whatsapp.GroupInfo
 	if portal.IsPrivateChat() {
 		puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
 		if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
@@ -1099,7 +1095,7 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 
 func (portal *Portal) IsPrivateChat() bool {
 	if portal.isPrivate == nil {
-		val := strings.HasSuffix(portal.Key.JID, whatsappExt.NewUserSuffix)
+		val := strings.HasSuffix(portal.Key.JID, whatsapp.NewUserSuffix)
 		portal.isPrivate = &val
 	}
 	return *portal.isPrivate
@@ -1152,7 +1148,7 @@ func (portal *Portal) SetReply(content *event.MessageEventContent, info whatsapp
 	return
 }
 
-func (portal *Portal) HandleMessageRevoke(user *User, message whatsappExt.MessageRevocation) {
+func (portal *Portal) HandleMessageRevoke(user *User, message whatsapp.MessageRevocation) {
 	msg := portal.bridge.DB.Message.GetByJID(portal.Key, message.Id)
 	if msg == nil || msg.IsFakeMXID() {
 		return
@@ -1794,7 +1790,7 @@ func (portal *Portal) convertGifToVideo(gif []byte) ([]byte, error) {
 
 func (portal *Portal) preprocessMatrixMedia(sender *User, relaybotFormatted bool, content *event.MessageEventContent, eventID id.EventID, mediaType whatsapp.MediaType) *MediaUpload {
 	var caption string
-	var mentionedJIDs []types.WhatsAppID
+	var mentionedJIDs []whatsapp.JID
 	if relaybotFormatted {
 		caption, mentionedJIDs = portal.bridge.Formatter.ParseMatrix(content.FormattedBody)
 	}
@@ -1851,7 +1847,7 @@ func (portal *Portal) preprocessMatrixMedia(sender *User, relaybotFormatted bool
 
 type MediaUpload struct {
 	Caption       string
-	MentionedJIDs []types.WhatsAppID
+	MentionedJIDs []whatsapp.JID
 	URL           string
 	MediaKey      []byte
 	FileEncSHA256 []byte

+ 3 - 4
provisioning.go

@@ -27,12 +27,11 @@ import (
 	"time"
 
 	"github.com/gorilla/websocket"
-	log "maunium.net/go/maulogger/v2"
 
 	"github.com/Rhymen/go-whatsapp"
-	"maunium.net/go/mautrix/id"
 
-	whatsappExt "maunium.net/go/mautrix-whatsapp/whatsapp-ext"
+	log "maunium.net/go/maulogger/v2"
+	"maunium.net/go/mautrix/id"
 )
 
 type ProvisioningAPI struct {
@@ -433,7 +432,7 @@ func (prov *ProvisioningAPI) Login(w http.ResponseWriter, r *http.Request) {
 	}
 	user.log.Debugln("Successful login via provisioning API")
 	user.ConnectionErrors = 0
-	user.JID = strings.Replace(user.Conn.Info.Wid, whatsappExt.OldUserSuffix, whatsappExt.NewUserSuffix, 1)
+	user.JID = strings.Replace(user.Conn.Info.Wid, whatsapp.OldUserSuffix, whatsapp.NewUserSuffix, 1)
 	user.addToJIDMap()
 	user.SetSession(&session)
 	_ = c.WriteJSON(map[string]interface{}{

+ 8 - 11
puppet.go

@@ -22,21 +22,18 @@ import (
 	"regexp"
 	"strings"
 
-	log "maunium.net/go/maulogger/v2"
-
 	"github.com/Rhymen/go-whatsapp"
 
+	log "maunium.net/go/maulogger/v2"
 	"maunium.net/go/mautrix/appservice"
 	"maunium.net/go/mautrix/id"
 
 	"maunium.net/go/mautrix-whatsapp/database"
-	"maunium.net/go/mautrix-whatsapp/types"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 var userIDRegex *regexp.Regexp
 
-func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (types.WhatsAppID, bool) {
+func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (whatsapp.JID, bool) {
 	if userIDRegex == nil {
 		userIDRegex = regexp.MustCompile(fmt.Sprintf("^@%s:%s$",
 			bridge.Config.Bridge.FormatUsername("([0-9]+)"),
@@ -47,7 +44,7 @@ func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (types.WhatsAppID, bool) {
 		return "", false
 	}
 
-	jid := types.WhatsAppID(match[1] + whatsappExt.NewUserSuffix)
+	jid := whatsapp.JID(match[1] + whatsapp.NewUserSuffix)
 	return jid, true
 }
 
@@ -60,7 +57,7 @@ func (bridge *Bridge) GetPuppetByMXID(mxid id.UserID) *Puppet {
 	return bridge.GetPuppetByJID(jid)
 }
 
-func (bridge *Bridge) GetPuppetByJID(jid types.WhatsAppID) *Puppet {
+func (bridge *Bridge) GetPuppetByJID(jid whatsapp.JID) *Puppet {
 	bridge.puppetsLock.Lock()
 	defer bridge.puppetsLock.Unlock()
 	puppet, ok := bridge.puppets[jid]
@@ -125,12 +122,12 @@ func (bridge *Bridge) dbPuppetsToPuppets(dbPuppets []*database.Puppet) []*Puppet
 	return output
 }
 
-func (bridge *Bridge) FormatPuppetMXID(jid types.WhatsAppID) id.UserID {
+func (bridge *Bridge) FormatPuppetMXID(jid whatsapp.JID) id.UserID {
 	return id.NewUserID(
 		bridge.Config.Bridge.FormatUsername(
 			strings.Replace(
 				jid,
-				whatsappExt.NewUserSuffix, "", 1)),
+				whatsapp.NewUserSuffix, "", 1)),
 		bridge.Config.Homeserver.Domain)
 }
 
@@ -161,7 +158,7 @@ type Puppet struct {
 }
 
 func (puppet *Puppet) PhoneNumber() string {
-	return strings.Replace(puppet.JID, whatsappExt.NewUserSuffix, "", 1)
+	return strings.Replace(puppet.JID, whatsapp.NewUserSuffix, "", 1)
 }
 
 func (puppet *Puppet) IntentFor(portal *Portal) *appservice.IntentAPI {
@@ -181,7 +178,7 @@ func (puppet *Puppet) DefaultIntent() *appservice.IntentAPI {
 	return puppet.bridge.AS.Intent(puppet.MXID)
 }
 
-func (puppet *Puppet) UpdateAvatar(source *User, avatar *whatsappExt.ProfilePicInfo) bool {
+func (puppet *Puppet) UpdateAvatar(source *User, avatar *whatsapp.ProfilePicInfo) bool {
 	if avatar == nil {
 		var err error
 		avatar, err = source.Conn.GetProfilePicThumb(puppet.JID)

+ 0 - 23
types/types.go

@@ -1,23 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 types
-
-// WhatsAppID is a WhatsApp JID.
-type WhatsAppID = string
-
-// WhatsAppMessageID is the internal ID of a WhatsApp message.
-type WhatsAppMessageID = string

+ 112 - 124
user.go

@@ -40,13 +40,11 @@ import (
 	"maunium.net/go/mautrix/id"
 
 	"maunium.net/go/mautrix-whatsapp/database"
-	"maunium.net/go/mautrix-whatsapp/types"
-	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 type User struct {
 	*database.User
-	Conn *whatsappExt.ExtendedConn
+	Conn *whatsapp.Conn
 
 	bridge *Bridge
 	log    log.Logger
@@ -91,7 +89,7 @@ func (bridge *Bridge) GetUserByMXID(userID id.UserID) *User {
 	return user
 }
 
-func (bridge *Bridge) GetUserByJID(userID types.WhatsAppID) *User {
+func (bridge *Bridge) GetUserByJID(userID whatsapp.JID) *User {
 	bridge.usersLock.Lock()
 	defer bridge.usersLock.Unlock()
 	user, ok := bridge.usersByJID[userID]
@@ -264,7 +262,7 @@ func (user *User) Connect(evenIfNoSession bool) bool {
 		user.connLock.Unlock()
 		return false
 	}
-	user.Conn = whatsappExt.ExtendConn(conn)
+	user.Conn = conn
 	user.log.Debugln("WhatsApp connection successful")
 	user.Conn.AddHandler(user)
 	user.connLock.Unlock()
@@ -419,7 +417,7 @@ func (user *User) Login(ce *CommandEvent) {
 	// TODO there's a bit of duplication between this and the provisioning API login method
 	//      Also between the two logout methods (commands.go and provisioning.go)
 	user.ConnectionErrors = 0
-	user.JID = strings.Replace(user.Conn.Info.Wid, whatsappExt.OldUserSuffix, whatsappExt.NewUserSuffix, 1)
+	user.JID = strings.Replace(user.Conn.Info.Wid, whatsapp.OldUserSuffix, whatsapp.NewUserSuffix, 1)
 	user.addToJIDMap()
 	user.SetSession(&session)
 	ce.Reply("Successfully logged in, synchronizing chats...")
@@ -501,7 +499,7 @@ func (user *User) sendMarkdownBridgeAlert(formatString string, args ...interface
 	}
 }
 
-func (user *User) postConnPing(conn *whatsappExt.ExtendedConn) bool {
+func (user *User) postConnPing(conn *whatsapp.Conn) bool {
 	if user.Conn != conn {
 		user.log.Warnln("Connection changed before scheduled post-connection ping, canceling ping")
 		return false
@@ -528,7 +526,7 @@ func (user *User) postConnPing(conn *whatsappExt.ExtendedConn) bool {
 	}
 }
 
-func (user *User) intPostLogin(conn *whatsappExt.ExtendedConn) {
+func (user *User) intPostLogin(conn *whatsapp.Conn) {
 	defer user.syncWait.Done()
 	user.lastReconnection = time.Now().Unix()
 	user.createCommunity()
@@ -559,8 +557,60 @@ func (user *User) intPostLogin(conn *whatsappExt.ExtendedConn) {
 	}
 }
 
-func (user *User) HandleStreamEvent(evt whatsappExt.StreamEvent) {
-	if evt.Type == whatsappExt.StreamSleep {
+type InfoGetter interface {
+	GetInfo() whatsapp.MessageInfo
+}
+
+func (user *User) HandleEvent(event interface{}) {
+	switch v := event.(type) {
+	case whatsapp.TextMessage, whatsapp.ImageMessage, whatsapp.StickerMessage, whatsapp.VideoMessage,
+		whatsapp.AudioMessage, whatsapp.DocumentMessage, whatsapp.ContactMessage, whatsapp.StubMessage,
+		whatsapp.LocationMessage:
+		info := v.(InfoGetter).GetInfo()
+		user.messageInput <- PortalMessage{info.RemoteJid, user, v, info.Timestamp}
+	case whatsapp.MessageRevocation:
+		user.messageInput <- PortalMessage{v.RemoteJid, user, v, 0}
+	case whatsapp.StreamEvent:
+		user.HandleStreamEvent(v)
+	case []whatsapp.Chat:
+		user.HandleChatList(v)
+	case []whatsapp.Contact:
+		user.HandleContactList(v)
+	case error:
+		user.HandleError(v)
+	case whatsapp.Contact:
+		go user.HandleNewContact(v)
+	case whatsapp.BatteryMessage:
+		user.HandleBatteryMessage(v)
+	case whatsapp.CallInfo:
+		user.HandleCallInfo(v)
+	case whatsapp.PresenceEvent:
+		go user.HandlePresence(v)
+	case whatsapp.JSONMsgInfo:
+		go user.HandleMsgInfo(v)
+	case whatsapp.ReceivedMessage:
+		user.HandleReceivedMessage(v)
+	case whatsapp.ReadMessage:
+		user.HandleReadMessage(v)
+	case whatsapp.JSONCommand:
+		user.HandleCommand(v)
+	case whatsapp.ChatUpdate:
+		user.HandleChatUpdate(v)
+	case json.RawMessage:
+		user.HandleJSONMessage(v)
+	case *waProto.WebMessageInfo:
+		user.updateLastConnectionIfNecessary()
+		// TODO trace log
+		user.log.Debugfln("WebMessageInfo: %+v", v)
+	case *waBinary.Node:
+		user.log.Debugfln("Unknown binary message: %+v", v)
+	default:
+		user.log.Debugfln("Unknown type of event in HandleEvent: %T", v)
+	}
+}
+
+func (user *User) HandleStreamEvent(evt whatsapp.StreamEvent) {
+	if evt.Type == whatsapp.StreamSleep {
 		if user.lastReconnection+60 > time.Now().Unix() {
 			user.lastReconnection = 0
 			user.log.Infoln("Stream went to sleep soon after reconnection, making new post-connection ping in 20 seconds")
@@ -738,7 +788,7 @@ func (user *User) syncPuppets(contacts map[string]whatsapp.Contact) {
 	}
 	user.log.Infoln("Syncing puppet info from contacts")
 	for jid, contact := range contacts {
-		if strings.HasSuffix(jid, whatsappExt.NewUserSuffix) {
+		if strings.HasSuffix(jid, whatsapp.NewUserSuffix) {
 			puppet := user.bridge.GetPuppetByJID(contact.Jid)
 			puppet.Sync(user, contact)
 		}
@@ -841,19 +891,11 @@ func (user *User) tryReconnect(msg string) {
 	}
 }
 
-func (user *User) ShouldCallSynchronously() bool {
-	return true
-}
-
-func (user *User) HandleJSONParseError(err error) {
-	user.log.Errorln("WhatsApp JSON parse error:", err)
-}
-
-func (user *User) PortalKey(jid types.WhatsAppID) database.PortalKey {
+func (user *User) PortalKey(jid whatsapp.JID) database.PortalKey {
 	return database.NewPortalKey(jid, user.JID)
 }
 
-func (user *User) GetPortalByJID(jid types.WhatsAppID) *Portal {
+func (user *User) GetPortalByJID(jid whatsapp.JID) *Portal {
 	return user.bridge.GetPortalByJID(user.PortalKey(jid))
 }
 
@@ -888,13 +930,11 @@ func (user *User) handleMessageLoop() {
 
 func (user *User) HandleNewContact(contact whatsapp.Contact) {
 	user.log.Debugfln("Contact message: %+v", contact)
-	go func() {
-		if strings.HasSuffix(contact.Jid, whatsappExt.OldUserSuffix) {
-			contact.Jid = strings.Replace(contact.Jid, whatsappExt.OldUserSuffix, whatsappExt.NewUserSuffix, -1)
-		}
-		puppet := user.bridge.GetPuppetByJID(contact.Jid)
-		puppet.UpdateName(user, contact)
-	}()
+	if strings.HasSuffix(contact.Jid, whatsapp.OldUserSuffix) {
+		contact.Jid = strings.Replace(contact.Jid, whatsapp.OldUserSuffix, whatsapp.NewUserSuffix, -1)
+	}
+	puppet := user.bridge.GetPuppetByJID(contact.Jid)
+	puppet.UpdateName(user, contact)
 }
 
 func (user *User) HandleBatteryMessage(battery whatsapp.BatteryMessage) {
@@ -914,53 +954,13 @@ func (user *User) HandleBatteryMessage(battery whatsapp.BatteryMessage) {
 	}
 }
 
-func (user *User) HandleTextMessage(message whatsapp.TextMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleImageMessage(message whatsapp.ImageMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleStickerMessage(message whatsapp.StickerMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleAudioMessage(message whatsapp.AudioMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleDocumentMessage(message whatsapp.DocumentMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleContactMessage(message whatsapp.ContactMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleStubMessage(message whatsapp.StubMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleLocationMessage(message whatsapp.LocationMessage) {
-	user.messageInput <- PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp}
-}
-
-func (user *User) HandleMessageRevoke(message whatsappExt.MessageRevocation) {
-	user.messageInput <- PortalMessage{message.RemoteJid, user, message, 0}
-}
-
 type FakeMessage struct {
 	Text  string
 	ID    string
 	Alert bool
 }
 
-func (user *User) HandleCallInfo(info whatsappExt.CallInfo) {
+func (user *User) HandleCallInfo(info whatsapp.CallInfo) {
 	if info.Data != nil {
 		return
 	}
@@ -968,19 +968,19 @@ func (user *User) HandleCallInfo(info whatsappExt.CallInfo) {
 		ID: info.ID,
 	}
 	switch info.Type {
-	case whatsappExt.CallOffer:
+	case whatsapp.CallOffer:
 		if !user.bridge.Config.Bridge.CallNotices.Start {
 			return
 		}
 		data.Text = "Incoming call"
 		data.Alert = true
-	case whatsappExt.CallOfferVideo:
+	case whatsapp.CallOfferVideo:
 		if !user.bridge.Config.Bridge.CallNotices.Start {
 			return
 		}
 		data.Text = "Incoming video call"
 		data.Alert = true
-	case whatsappExt.CallTerminate:
+	case whatsapp.CallTerminate:
 		if !user.bridge.Config.Bridge.CallNotices.End {
 			return
 		}
@@ -995,7 +995,7 @@ func (user *User) HandleCallInfo(info whatsappExt.CallInfo) {
 	}
 }
 
-func (user *User) HandlePresence(info whatsappExt.Presence) {
+func (user *User) HandlePresence(info whatsapp.PresenceEvent) {
 	puppet := user.bridge.GetPuppetByJID(info.SenderJID)
 	switch info.Status {
 	case whatsapp.PresenceUnavailable:
@@ -1023,33 +1023,31 @@ func (user *User) HandlePresence(info whatsappExt.Presence) {
 	}
 }
 
-func (user *User) HandleMsgInfo(info whatsappExt.MsgInfo) {
-	if (info.Command == whatsappExt.MsgInfoCommandAck || info.Command == whatsappExt.MsgInfoCommandAcks) && info.Acknowledgement == whatsappExt.AckMessageRead {
+func (user *User) HandleMsgInfo(info whatsapp.JSONMsgInfo) {
+	if (info.Command == whatsapp.MsgInfoCommandAck || info.Command == whatsapp.MsgInfoCommandAcks) && info.Acknowledgement == whatsapp.AckMessageRead {
 		portal := user.GetPortalByJID(info.ToJID)
 		if len(portal.MXID) == 0 {
 			return
 		}
 
-		go func() {
-			intent := user.bridge.GetPuppetByJID(info.SenderJID).IntentFor(portal)
-			for _, msgID := range info.IDs {
-				msg := user.bridge.DB.Message.GetByJID(portal.Key, msgID)
-				if msg == nil || msg.IsFakeMXID() {
-					continue
-				}
+		intent := user.bridge.GetPuppetByJID(info.SenderJID).IntentFor(portal)
+		for _, msgID := range info.IDs {
+			msg := user.bridge.DB.Message.GetByJID(portal.Key, msgID)
+			if msg == nil || msg.IsFakeMXID() {
+				continue
+			}
 
-				err := intent.MarkRead(portal.MXID, msg.MXID)
-				if err != nil {
-					user.log.Warnln("Failed to mark message %s as read by %s: %v", msg.MXID, info.SenderJID, err)
-				}
+			err := intent.MarkRead(portal.MXID, msg.MXID)
+			if err != nil {
+				user.log.Warnln("Failed to mark message %s as read by %s: %v", msg.MXID, info.SenderJID, err)
 			}
-		}()
+		}
 	}
 }
 
 func (user *User) HandleReceivedMessage(received whatsapp.ReceivedMessage) {
 	if received.Type == "read" {
-		user.markSelfRead(received.Jid, received.Index)
+		go user.markSelfRead(received.Jid, received.Index)
 	} else {
 		user.log.Debugfln("Unknown received message type: %+v", received)
 	}
@@ -1057,12 +1055,12 @@ func (user *User) HandleReceivedMessage(received whatsapp.ReceivedMessage) {
 
 func (user *User) HandleReadMessage(read whatsapp.ReadMessage) {
 	user.log.Debugfln("Received chat read message: %+v", read)
-	user.markSelfRead(read.Jid, "")
+	go user.markSelfRead(read.Jid, "")
 }
 
 func (user *User) markSelfRead(jid, messageID string) {
-	if strings.HasSuffix(jid, whatsappExt.OldUserSuffix) {
-		jid = strings.Replace(jid, whatsappExt.OldUserSuffix, whatsappExt.NewUserSuffix, -1)
+	if strings.HasSuffix(jid, whatsapp.OldUserSuffix) {
+		jid = strings.Replace(jid, whatsapp.OldUserSuffix, whatsapp.NewUserSuffix, -1)
 	}
 	puppet := user.bridge.GetPuppetByJID(user.JID)
 	if puppet == nil {
@@ -1096,17 +1094,17 @@ func (user *User) markSelfRead(jid, messageID string) {
 	}
 }
 
-func (user *User) HandleCommand(cmd whatsappExt.Command) {
+func (user *User) HandleCommand(cmd whatsapp.JSONCommand) {
 	switch cmd.Type {
-	case whatsappExt.CommandPicture:
-		if strings.HasSuffix(cmd.JID, whatsappExt.NewUserSuffix) {
+	case whatsapp.CommandPicture:
+		if strings.HasSuffix(cmd.JID, whatsapp.NewUserSuffix) {
 			puppet := user.bridge.GetPuppetByJID(cmd.JID)
 			go puppet.UpdateAvatar(user, cmd.ProfilePicInfo)
 		} else if user.bridge.Config.Bridge.ChatMetaSync {
 			portal := user.GetPortalByJID(cmd.JID)
 			go portal.UpdateAvatar(user, cmd.ProfilePicInfo, true)
 		}
-	case whatsappExt.CommandDisconnect:
+	case whatsapp.CommandDisconnect:
 		if cmd.Kind == "replaced" {
 			user.cleanDisconnection = true
 			go user.sendMarkdownBridgeAlert("\u26a0 Your WhatsApp connection was closed by the server because you opened another WhatsApp Web client.\n\n" +
@@ -1119,14 +1117,14 @@ func (user *User) HandleCommand(cmd whatsappExt.Command) {
 	}
 }
 
-func (user *User) HandleChatUpdate(cmd whatsappExt.ChatUpdate) {
-	if cmd.Command != whatsappExt.ChatUpdateCommandAction {
+func (user *User) HandleChatUpdate(cmd whatsapp.ChatUpdate) {
+	if cmd.Command != whatsapp.ChatUpdateCommandAction {
 		return
 	}
 
 	portal := user.GetPortalByJID(cmd.JID)
 	if len(portal.MXID) == 0 {
-		if cmd.Data.Action == whatsappExt.ChatActionIntroduce || cmd.Data.Action == whatsappExt.ChatActionCreate {
+		if cmd.Data.Action == whatsapp.ChatActionIntroduce || cmd.Data.Action == whatsapp.ChatActionCreate {
 			go func() {
 				err := portal.CreateMatrixRoom(user)
 				if err != nil {
@@ -1139,11 +1137,11 @@ func (user *User) HandleChatUpdate(cmd whatsappExt.ChatUpdate) {
 
 	// These don't come down the message history :(
 	switch cmd.Data.Action {
-	case whatsappExt.ChatActionAddTopic:
-		go portal.UpdateTopic(cmd.Data.AddTopic.Topic, cmd.Data.SenderJID, nil,true)
-	case whatsappExt.ChatActionRemoveTopic:
-		go portal.UpdateTopic("", cmd.Data.SenderJID, nil,true)
-	case whatsappExt.ChatActionRemove:
+	case whatsapp.ChatActionAddTopic:
+		go portal.UpdateTopic(cmd.Data.AddTopic.Topic, cmd.Data.SenderJID, nil, true)
+	case whatsapp.ChatActionRemoveTopic:
+		go portal.UpdateTopic("", cmd.Data.SenderJID, nil, true)
+	case whatsapp.ChatActionRemove:
 		// We ignore leaving groups in the message history to avoid accidentally leaving rejoined groups,
 		// but if we get a real-time command that says we left, it should be safe to bridge it.
 		if !user.bridge.Config.Bridge.ChatMetaSync {
@@ -1162,45 +1160,35 @@ func (user *User) HandleChatUpdate(cmd whatsappExt.ChatUpdate) {
 	}
 
 	switch cmd.Data.Action {
-	case whatsappExt.ChatActionNameChange:
+	case whatsapp.ChatActionNameChange:
 		go portal.UpdateName(cmd.Data.NameChange.Name, cmd.Data.SenderJID, nil, true)
-	case whatsappExt.ChatActionPromote:
+	case whatsapp.ChatActionPromote:
 		go portal.ChangeAdminStatus(cmd.Data.UserChange.JIDs, true)
-	case whatsappExt.ChatActionDemote:
+	case whatsapp.ChatActionDemote:
 		go portal.ChangeAdminStatus(cmd.Data.UserChange.JIDs, false)
-	case whatsappExt.ChatActionAnnounce:
+	case whatsapp.ChatActionAnnounce:
 		go portal.RestrictMessageSending(cmd.Data.Announce)
-	case whatsappExt.ChatActionRestrict:
+	case whatsapp.ChatActionRestrict:
 		go portal.RestrictMetadataChanges(cmd.Data.Restrict)
-	case whatsappExt.ChatActionRemove:
+	case whatsapp.ChatActionRemove:
 		go portal.HandleWhatsAppKick(nil, cmd.Data.SenderJID, cmd.Data.UserChange.JIDs)
-	case whatsappExt.ChatActionAdd:
+	case whatsapp.ChatActionAdd:
 		go portal.HandleWhatsAppInvite(cmd.Data.SenderJID, nil, cmd.Data.UserChange.JIDs)
-	case whatsappExt.ChatActionIntroduce:
+	case whatsapp.ChatActionIntroduce:
 		if cmd.Data.SenderJID != "unknown" {
 			go portal.Sync(user, whatsapp.Contact{Jid: portal.Key.JID})
 		}
 	}
 }
 
-func (user *User) HandleJsonMessage(message string) {
-	var msg json.RawMessage
-	err := json.Unmarshal([]byte(message), &msg)
-	if err != nil {
+func (user *User) HandleJSONMessage(message json.RawMessage) {
+	if !json.Valid(message) {
 		return
 	}
-	user.log.Debugln("JSON message:", message)
+	user.log.Debugfln("JSON message: %s", message)
 	user.updateLastConnectionIfNecessary()
 }
 
-func (user *User) HandleRawMessage(message *waProto.WebMessageInfo) {
-	user.updateLastConnectionIfNecessary()
-}
-
-func (user *User) HandleUnknownBinaryNode(node *waBinary.Node) {
-	user.log.Debugfln("Unknown binary message: %+v", node)
-}
-
 func (user *User) NeedsRelaybot(portal *Portal) bool {
 	return !user.HasSession() || !user.IsInPortal(portal.Key)
 }

+ 0 - 72
whatsapp-ext/call.go

@@ -1,72 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type CallInfoType string
-
-const (
-	CallOffer        CallInfoType = "offer"
-	CallOfferVideo   CallInfoType = "offer_video"
-	CallTransport    CallInfoType = "transport"
-	CallRelayLatency CallInfoType = "relaylatency"
-	CallTerminate    CallInfoType = "terminate"
-)
-
-type CallInfo struct {
-	ID   string       `json:"id"`
-	Type CallInfoType `json:"type"`
-	From string       `json:"from"`
-
-	Platform string `json:"platform"`
-	Version  []int  `json:"version"`
-
-	Data [][]interface{} `json:"data"`
-}
-
-type CallInfoHandler interface {
-	whatsapp.Handler
-	HandleCallInfo(CallInfo)
-}
-
-func (ext *ExtendedConn) handleMessageCall(message []byte) {
-	var event CallInfo
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	event.From = strings.Replace(event.From, OldUserSuffix, NewUserSuffix, 1)
-	for _, handler := range ext.handlers {
-		callInfoHandler, ok := handler.(CallInfoHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(callInfoHandler) {
-			callInfoHandler.HandleCallInfo(event)
-		} else {
-			go callInfoHandler.HandleCallInfo(event)
-		}
-	}
-}

+ 0 - 183
whatsapp-ext/chat.go

@@ -1,183 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type ChatUpdateCommand string
-
-const (
-	ChatUpdateCommandAction ChatUpdateCommand = "action"
-)
-
-type ChatUpdate struct {
-	JID     string            `json:"id"`
-	Command ChatUpdateCommand `json:"cmd"`
-	Data    ChatUpdateData    `json:"data"`
-}
-
-type ChatActionType string
-
-const (
-	ChatActionNameChange  ChatActionType = "subject"
-	ChatActionAddTopic    ChatActionType = "desc_add"
-	ChatActionRemoveTopic ChatActionType = "desc_remove"
-	ChatActionRestrict    ChatActionType = "restrict"
-	ChatActionAnnounce    ChatActionType = "announce"
-	ChatActionPromote     ChatActionType = "promote"
-	ChatActionDemote      ChatActionType = "demote"
-	ChatActionIntroduce   ChatActionType = "introduce"
-	ChatActionCreate      ChatActionType = "create"
-	ChatActionRemove      ChatActionType = "remove"
-	ChatActionAdd         ChatActionType = "add"
-)
-
-type ChatUpdateData struct {
-	Action    ChatActionType
-	SenderJID string
-
-	NameChange struct {
-		Name  string `json:"subject"`
-		SetAt int64  `json:"s_t"`
-		SetBy string `json:"s_o"`
-	}
-
-	AddTopic struct {
-		Topic string `json:"desc"`
-		ID    string `json:"descId"`
-		SetAt int64  `json:"descTime"`
-		SetBy string `json:"descOwner"`
-	}
-
-	RemoveTopic struct {
-		ID string `json:"descId"`
-	}
-
-	Introduce struct {
-		CreationTime int64    `json:"creation"`
-		Admins       []string `json:"admins"`
-		SuperAdmins  []string `json:"superadmins"`
-		Regulars     []string `json:"regulars"`
-	}
-
-	Restrict bool
-
-	Announce bool
-
-	UserChange struct {
-		JIDs []string `json:"participants"`
-	}
-}
-
-func (cud *ChatUpdateData) UnmarshalJSON(data []byte) error {
-	var arr []json.RawMessage
-	err := json.Unmarshal(data, &arr)
-	if err != nil {
-		return err
-	} else if len(arr) < 3 {
-		return nil
-	}
-
-	err = json.Unmarshal(arr[0], &cud.Action)
-	if err != nil {
-		return err
-	}
-
-	err = json.Unmarshal(arr[1], &cud.SenderJID)
-	if err != nil {
-		return err
-	}
-	cud.SenderJID = strings.Replace(cud.SenderJID, OldUserSuffix, NewUserSuffix, 1)
-
-	var unmarshalTo interface{}
-	switch cud.Action {
-	case ChatActionIntroduce, ChatActionCreate:
-		err = json.Unmarshal(arr[2], &cud.NameChange)
-		if err != nil {
-			return err
-		}
-		err = json.Unmarshal(arr[2], &cud.AddTopic)
-		if err != nil {
-			return err
-		}
-		unmarshalTo = &cud.Introduce
-	case ChatActionNameChange:
-		unmarshalTo = &cud.NameChange
-	case ChatActionAddTopic:
-		unmarshalTo = &cud.AddTopic
-	case ChatActionRemoveTopic:
-		unmarshalTo = &cud.RemoveTopic
-	case ChatActionRestrict:
-		unmarshalTo = &cud.Restrict
-	case ChatActionAnnounce:
-		unmarshalTo = &cud.Announce
-	case ChatActionPromote, ChatActionDemote, ChatActionRemove, ChatActionAdd:
-		unmarshalTo = &cud.UserChange
-	default:
-		return nil
-	}
-	err = json.Unmarshal(arr[2], unmarshalTo)
-	if err != nil {
-		return err
-	}
-	cud.NameChange.SetBy = strings.Replace(cud.NameChange.SetBy, OldUserSuffix, NewUserSuffix, 1)
-	for index, jid := range cud.UserChange.JIDs {
-		cud.UserChange.JIDs[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
-	}
-	for index, jid := range cud.Introduce.SuperAdmins {
-		cud.Introduce.SuperAdmins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
-	}
-	for index, jid := range cud.Introduce.Admins {
-		cud.Introduce.Admins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
-	}
-	for index, jid := range cud.Introduce.Regulars {
-		cud.Introduce.Regulars[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
-	}
-	return nil
-}
-
-type ChatUpdateHandler interface {
-	whatsapp.Handler
-	HandleChatUpdate(ChatUpdate)
-}
-
-func (ext *ExtendedConn) handleMessageChatUpdate(message []byte) {
-	var event ChatUpdate
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
-	for _, handler := range ext.handlers {
-		chatUpdateHandler, ok := handler.(ChatUpdateHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(chatUpdateHandler) {
-			chatUpdateHandler.HandleChatUpdate(event)
-		} else {
-			go chatUpdateHandler.HandleChatUpdate(event)
-		}
-	}
-}

+ 0 - 69
whatsapp-ext/cmd.go

@@ -1,69 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type CommandType string
-
-const (
-	CommandPicture    CommandType = "picture"
-	CommandDisconnect CommandType = "disconnect"
-)
-
-type Command struct {
-	Type CommandType `json:"type"`
-	JID  string      `json:"jid"`
-
-	*ProfilePicInfo
-	Kind string `json:"kind"`
-
-	Raw json.RawMessage `json:"-"`
-}
-
-type CommandHandler interface {
-	whatsapp.Handler
-	HandleCommand(Command)
-}
-
-func (ext *ExtendedConn) handleMessageCommand(message []byte) {
-	var event Command
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	event.Raw = message
-	event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
-	for _, handler := range ext.handlers {
-		commandHandler, ok := handler.(CommandHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(commandHandler) {
-			commandHandler.HandleCommand(event)
-		} else {
-			go commandHandler.HandleCommand(event)
-		}
-	}
-}

+ 0 - 65
whatsapp-ext/conn.go

@@ -1,65 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type ConnInfo struct {
-	ProtocolVersion []int `json:"protoVersion"`
-	BinaryVersion   int   `json:"binVersion"`
-	Phone           struct {
-		WhatsAppVersion    string `json:"wa_version"`
-		MCC                string `json:"mcc"`
-		MNC                string `json:"mnc"`
-		OSVersion          string `json:"os_version"`
-		DeviceManufacturer string `json:"device_manufacturer"`
-		DeviceModel        string `json:"device_model"`
-		OSBuildNumber      string `json:"os_build_number"`
-	} `json:"phone"`
-	Features map[string]interface{} `json:"features"`
-	PushName string                 `json:"pushname"`
-}
-
-type ConnInfoHandler interface {
-	whatsapp.Handler
-	HandleConnInfo(ConnInfo)
-}
-
-func (ext *ExtendedConn) handleMessageConn(message []byte) {
-	var event ConnInfo
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	for _, handler := range ext.handlers {
-		connInfoHandler, ok := handler.(ConnInfoHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(connInfoHandler) {
-			connInfoHandler.HandleConnInfo(event)
-		} else {
-			go connInfoHandler.HandleConnInfo(event)
-		}
-	}
-}

+ 0 - 68
whatsapp-ext/group.go

@@ -1,68 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"fmt"
-
-	"maunium.net/go/mautrix-whatsapp/types"
-)
-
-type CreateGroupResponse struct {
-	Status       int              `json:"status"`
-	GroupID      types.WhatsAppID `json:"gid"`
-	Participants map[types.WhatsAppID]struct {
-		Code string `json:"code"`
-	} `json:"participants"`
-
-	Source string `json:"-"`
-}
-
-type actualCreateGroupResponse struct {
-	Status       int              `json:"status"`
-	GroupID      types.WhatsAppID `json:"gid"`
-	Participants []map[types.WhatsAppID]struct {
-		Code string `json:"code"`
-	} `json:"participants"`
-}
-
-func (ext *ExtendedConn) CreateGroup(subject string, participants []types.WhatsAppID) (*CreateGroupResponse, error) {
-	respChan, err := ext.Conn.CreateGroup(subject, participants)
-	if err != nil {
-		return nil, err
-	}
-	var resp CreateGroupResponse
-	var actualResp actualCreateGroupResponse
-	resp.Source = <-respChan
-	fmt.Println(">>>>>>", resp.Source)
-	err = json.Unmarshal([]byte(resp.Source), &actualResp)
-	if err != nil {
-		return nil, err
-	}
-	resp.Status = actualResp.Status
-	resp.GroupID = actualResp.GroupID
-	resp.Participants = make(map[types.WhatsAppID]struct {
-		Code string `json:"code"`
-	})
-	for _, participantMap := range actualResp.Participants {
-		for jid, status := range participantMap {
-			resp.Participants[jid] = status
-		}
-	}
-	return &resp, nil
-}

+ 0 - 105
whatsapp-ext/jsonmessage.go

@@ -1,105 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type JSONMessage []json.RawMessage
-
-type JSONMessageType string
-
-const (
-	MessageMsgInfo  JSONMessageType = "MsgInfo"
-	MessageMsg      JSONMessageType = "Msg"
-	MessagePresence JSONMessageType = "Presence"
-	MessageStream   JSONMessageType = "Stream"
-	MessageConn     JSONMessageType = "Conn"
-	MessageProps    JSONMessageType = "Props"
-	MessageCmd      JSONMessageType = "Cmd"
-	MessageChat     JSONMessageType = "Chat"
-	MessageCall     JSONMessageType = "Call"
-)
-
-func (ext *ExtendedConn) HandleError(error) {}
-
-type UnhandledJSONMessageHandler interface {
-	whatsapp.Handler
-	HandleUnhandledJSONMessage(string)
-}
-
-type JSONParseErrorHandler interface {
-	whatsapp.Handler
-	HandleJSONParseError(error)
-}
-
-func (ext *ExtendedConn) jsonParseError(err error) {
-	for _, handler := range ext.handlers {
-		errorHandler, ok := handler.(JSONParseErrorHandler)
-		if !ok {
-			continue
-		}
-		errorHandler.HandleJSONParseError(err)
-	}
-}
-
-func (ext *ExtendedConn) HandleJsonMessage(message string) {
-	msg := JSONMessage{}
-	err := json.Unmarshal([]byte(message), &msg)
-	if err != nil || len(msg) < 2 {
-		ext.jsonParseError(err)
-		return
-	}
-
-	var msgType JSONMessageType
-	json.Unmarshal(msg[0], &msgType)
-
-	switch msgType {
-	case MessagePresence:
-		ext.handleMessagePresence(msg[1])
-	case MessageStream:
-		ext.handleMessageStream(msg[1:])
-	case MessageConn:
-		ext.handleMessageConn(msg[1])
-	case MessageProps:
-		ext.handleMessageProps(msg[1])
-	case MessageMsgInfo, MessageMsg:
-		ext.handleMessageMsgInfo(msgType, msg[1])
-	case MessageCmd:
-		ext.handleMessageCommand(msg[1])
-	case MessageChat:
-		ext.handleMessageChatUpdate(msg[1])
-	case MessageCall:
-		ext.handleMessageCall(msg[1])
-	default:
-		for _, handler := range ext.handlers {
-			ujmHandler, ok := handler.(UnhandledJSONMessageHandler)
-			if !ok {
-				continue
-			}
-
-			if ext.shouldCallSynchronously(ujmHandler) {
-				ujmHandler.HandleUnhandledJSONMessage(message)
-			} else {
-				go ujmHandler.HandleUnhandledJSONMessage(message)
-			}
-		}
-	}
-}

+ 0 - 95
whatsapp-ext/msginfo.go

@@ -1,95 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type MsgInfoCommand string
-
-const (
-	MsgInfoCommandAck  MsgInfoCommand = "ack"
-	MsgInfoCommandAcks MsgInfoCommand = "acks"
-)
-
-type Acknowledgement int
-
-const (
-	AckMessageSent      Acknowledgement = 1
-	AckMessageDelivered Acknowledgement = 2
-	AckMessageRead      Acknowledgement = 3
-)
-
-type JSONStringOrArray []string
-
-func (jsoa *JSONStringOrArray) UnmarshalJSON(data []byte) error {
-	var str string
-	if json.Unmarshal(data, &str) == nil {
-		*jsoa = []string{str}
-		return nil
-	}
-	var strs []string
-	json.Unmarshal(data, &strs)
-	*jsoa = strs
-	return nil
-}
-
-type MsgInfo struct {
-	Command         MsgInfoCommand    `json:"cmd"`
-	IDs             JSONStringOrArray `json:"id"`
-	Acknowledgement Acknowledgement   `json:"ack"`
-	MessageFromJID  string            `json:"from"`
-	SenderJID       string            `json:"participant"`
-	ToJID           string            `json:"to"`
-	Timestamp       int64             `json:"t"`
-}
-
-type MsgInfoHandler interface {
-	whatsapp.Handler
-	HandleMsgInfo(MsgInfo)
-}
-
-func (ext *ExtendedConn) handleMessageMsgInfo(msgType JSONMessageType, message []byte) {
-	var event MsgInfo
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	event.MessageFromJID = strings.Replace(event.MessageFromJID, OldUserSuffix, NewUserSuffix, 1)
-	event.SenderJID = strings.Replace(event.SenderJID, OldUserSuffix, NewUserSuffix, 1)
-	event.ToJID = strings.Replace(event.ToJID, OldUserSuffix, NewUserSuffix, 1)
-	if msgType == MessageMsg {
-		event.SenderJID = event.ToJID
-	}
-	for _, handler := range ext.handlers {
-		msgInfoHandler, ok := handler.(MsgInfoHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(msgInfoHandler) {
-			msgInfoHandler.HandleMsgInfo(event)
-		} else {
-			go msgInfoHandler.HandleMsgInfo(event)
-		}
-	}
-}

+ 0 - 64
whatsapp-ext/presence.go

@@ -1,64 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type Presence struct {
-	JID       string            `json:"id"`
-	SenderJID string            `json:"participant"`
-	Status    whatsapp.Presence `json:"type"`
-	Timestamp int64             `json:"t"`
-	Deny      bool              `json:"deny"`
-}
-
-type PresenceHandler interface {
-	whatsapp.Handler
-	HandlePresence(Presence)
-}
-
-func (ext *ExtendedConn) handleMessagePresence(message []byte) {
-	var event Presence
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
-	if len(event.SenderJID) == 0 {
-		event.SenderJID = event.JID
-	} else {
-		event.SenderJID = strings.Replace(event.SenderJID, OldUserSuffix, NewUserSuffix, 1)
-	}
-	for _, handler := range ext.handlers {
-		presenceHandler, ok := handler.(PresenceHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(presenceHandler) {
-			presenceHandler.HandlePresence(event)
-		} else {
-			go presenceHandler.HandlePresence(event)
-		}
-	}
-}

+ 0 - 73
whatsapp-ext/props.go

@@ -1,73 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type ProtocolProps struct {
-	WebPresence            bool   `json:"webPresence"`
-	NotificationQuery      bool   `json:"notificationQuery"`
-	FacebookCrashLog       bool   `json:"fbCrashlog"`
-	Bucket                 string `json:"bucket"`
-	GIFSearch              string `json:"gifSearch"`
-	Spam                   bool   `json:"SPAM"`
-	SetBlock               bool   `json:"SET_BLOCK"`
-	MessageInfo            bool   `json:"MESSAGE_INFO"`
-	MaxFileSize            int    `json:"maxFileSize"`
-	Media                  int    `json:"media"`
-	GroupNameLength        int    `json:"maxSubject"`
-	GroupDescriptionLength int    `json:"groupDescLength"`
-	MaxParticipants        int    `json:"maxParticipants"`
-	VideoMaxEdge           int    `json:"videoMaxEdge"`
-	ImageMaxEdge           int    `json:"imageMaxEdge"`
-	ImageMaxKilobytes      int    `json:"imageMaxKBytes"`
-	Edit                   int    `json:"edit"`
-	FwdUIStartTimestamp    int    `json:"fwdUiStartTs"`
-	GroupsV3               int    `json:"groupsV3"`
-	RestrictGroups         int    `json:"restrictGroups"`
-	AnnounceGroups         int    `json:"announceGroups"`
-}
-
-type ProtocolPropsHandler interface {
-	whatsapp.Handler
-	HandleProtocolProps(ProtocolProps)
-}
-
-func (ext *ExtendedConn) handleMessageProps(message []byte) {
-	var event ProtocolProps
-	err := json.Unmarshal(message, &event)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-	for _, handler := range ext.handlers {
-		protocolPropsHandler, ok := handler.(ProtocolPropsHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(protocolPropsHandler) {
-			protocolPropsHandler.HandleProtocolProps(event)
-		} else {
-			go protocolPropsHandler.HandleProtocolProps(event)
-		}
-	}
-}

+ 0 - 59
whatsapp-ext/protomessage.go

@@ -1,59 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"github.com/Rhymen/go-whatsapp"
-	"github.com/Rhymen/go-whatsapp/binary/proto"
-)
-
-type MessageRevokeHandler interface {
-	whatsapp.Handler
-	HandleMessageRevoke(key MessageRevocation)
-}
-
-type MessageRevocation struct {
-	Id          string
-	RemoteJid   string
-	FromMe      bool
-	Participant string
-}
-
-func (ext *ExtendedConn) HandleRawMessage(message *proto.WebMessageInfo) {
-	protoMsg := message.GetMessage().GetProtocolMessage()
-	if protoMsg != nil && protoMsg.GetType() == proto.ProtocolMessage_REVOKE {
-		key := protoMsg.GetKey()
-		deletedMessage := MessageRevocation{
-			Id:          key.GetId(),
-			RemoteJid:   key.GetRemoteJid(),
-			FromMe:      key.GetFromMe(),
-			Participant: key.GetParticipant(),
-		}
-		for _, handler := range ext.handlers {
-			mrHandler, ok := handler.(MessageRevokeHandler)
-			if !ok {
-				continue
-			}
-
-			if ext.shouldCallSynchronously(mrHandler) {
-				mrHandler.HandleMessageRevoke(deletedMessage)
-			} else {
-				go mrHandler.HandleMessageRevoke(deletedMessage)
-			}
-		}
-	}
-}

+ 0 - 76
whatsapp-ext/stream.go

@@ -1,76 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-type StreamType string
-
-const (
-	StreamUpdate = "update"
-	StreamSleep  = "asleep"
-)
-
-type StreamEvent struct {
-	Type StreamType
-
-	IsOutdated bool
-	Version    string
-
-	Extra []json.RawMessage
-}
-
-type StreamEventHandler interface {
-	whatsapp.Handler
-	HandleStreamEvent(StreamEvent)
-}
-
-func (ext *ExtendedConn) handleMessageStream(message []json.RawMessage) {
-	var event StreamEvent
-	err := json.Unmarshal(message[0], &event.Type)
-	if err != nil {
-		ext.jsonParseError(err)
-		return
-	}
-
-	if event.Type == StreamUpdate && len(message) >= 3 {
-		_ = json.Unmarshal(message[1], &event.IsOutdated)
-		_ = json.Unmarshal(message[2], &event.Version)
-		if len(message) >= 4 {
-			event.Extra = message[3:]
-		}
-	} else if len(message) >= 2 {
-		event.Extra = message[1:]
-	}
-
-	for _, handler := range ext.handlers {
-		streamHandler, ok := handler.(StreamEventHandler)
-		if !ok {
-			continue
-		}
-
-		if ext.shouldCallSynchronously(streamHandler) {
-			streamHandler.HandleStreamEvent(event)
-		} else {
-			go streamHandler.HandleStreamEvent(event)
-		}
-	}
-}

+ 0 - 164
whatsapp-ext/whatsapp.go

@@ -1,164 +0,0 @@
-// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
-// Copyright (C) 2019 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 whatsappExt
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"strings"
-
-	"github.com/Rhymen/go-whatsapp"
-)
-
-const (
-	OldUserSuffix = "@c.us"
-	NewUserSuffix = "@s.whatsapp.net"
-)
-
-type ExtendedConn struct {
-	*whatsapp.Conn
-
-	handlers []whatsapp.Handler
-}
-
-func ExtendConn(conn *whatsapp.Conn) *ExtendedConn {
-	ext := &ExtendedConn{
-		Conn: conn,
-	}
-	ext.Conn.AddHandler(ext)
-	return ext
-}
-
-func (ext *ExtendedConn) AddHandler(handler whatsapp.Handler) {
-	ext.Conn.AddHandler(handler)
-	ext.handlers = append(ext.handlers, handler)
-}
-
-func (ext *ExtendedConn) RemoveHandler(handler whatsapp.Handler) bool {
-	ext.Conn.RemoveHandler(handler)
-	for i, v := range ext.handlers {
-		if v == handler {
-			ext.handlers = append(ext.handlers[:i], ext.handlers[i+1:]...)
-			return true
-		}
-	}
-	return false
-}
-
-func (ext *ExtendedConn) RemoveHandlers() {
-	ext.Conn.RemoveHandlers()
-	ext.handlers = make([]whatsapp.Handler, 0)
-}
-
-func (ext *ExtendedConn) shouldCallSynchronously(handler whatsapp.Handler) bool {
-	sh, ok := handler.(whatsapp.SyncHandler)
-	return ok && sh.ShouldCallSynchronously()
-}
-
-func (ext *ExtendedConn) ShouldCallSynchronously() bool {
-	return true
-}
-
-type GroupInfo struct {
-	JID      string `json:"jid"`
-	OwnerJID string `json:"owner"`
-
-	Name        string `json:"subject"`
-	NameSetTime int64  `json:"subjectTime"`
-	NameSetBy   string `json:"subjectOwner"`
-
-	Announce bool `json:"announce"` // Can only admins send messages?
-
-	Topic      string `json:"desc"`
-	TopicID    string `json:"descId"`
-	TopicSetAt int64  `json:"descTime"`
-	TopicSetBy string `json:"descOwner"`
-
-	GroupCreated int64 `json:"creation"`
-
-	Status int16 `json:"status"`
-
-	Participants []struct {
-		JID          string `json:"id"`
-		IsAdmin      bool   `json:"isAdmin"`
-		IsSuperAdmin bool   `json:"isSuperAdmin"`
-	} `json:"participants"`
-}
-
-func (ext *ExtendedConn) GetGroupMetaData(jid string) (*GroupInfo, error) {
-	data, err := ext.Conn.GetGroupMetaData(jid)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get group metadata: %v", err)
-	}
-	content := <-data
-
-	info := &GroupInfo{}
-	err = json.Unmarshal([]byte(content), info)
-	if err != nil {
-		return info, fmt.Errorf("failed to unmarshal group metadata: %v", err)
-	}
-
-	for index, participant := range info.Participants {
-		info.Participants[index].JID = strings.Replace(participant.JID, OldUserSuffix, NewUserSuffix, 1)
-	}
-	info.NameSetBy = strings.Replace(info.NameSetBy, OldUserSuffix, NewUserSuffix, 1)
-	info.TopicSetBy = strings.Replace(info.TopicSetBy, OldUserSuffix, NewUserSuffix, 1)
-
-	return info, nil
-}
-
-type ProfilePicInfo struct {
-	URL string `json:"eurl"`
-	Tag string `json:"tag"`
-
-	Status int `json:"status"`
-}
-
-func (ppi *ProfilePicInfo) Download() (io.ReadCloser, error) {
-	resp, err := http.Get(ppi.URL)
-	if err != nil {
-		return nil, err
-	}
-	return resp.Body, nil
-}
-
-func (ppi *ProfilePicInfo) DownloadBytes() ([]byte, error) {
-	body, err := ppi.Download()
-	if err != nil {
-		return nil, err
-	}
-	defer body.Close()
-	data, err := ioutil.ReadAll(body)
-	return data, err
-}
-
-func (ext *ExtendedConn) GetProfilePicThumb(jid string) (*ProfilePicInfo, error) {
-	data, err := ext.Conn.GetProfilePicThumb(jid)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get avatar: %v", err)
-	}
-	content := <-data
-	info := &ProfilePicInfo{}
-	err = json.Unmarshal([]byte(content), info)
-	if err != nil {
-		return info, fmt.Errorf("failed to unmarshal avatar info: %v", err)
-	}
-	return info, nil
-}