Very spammy and buggy prototype.

master
Hugo Thunnissen 4 years ago
parent 2a175e4bfc
commit cd5696954c

@ -0,0 +1,84 @@
package botcommands
import (
"fmt"
"log"
"github.com/Rhymen/go-whatsapp"
"github.com/hugot/go-deltachat/deltachat"
)
type Database interface {
GetWhappJIDForDCID(DCID uint32) (*string, error)
}
func NewWhappBridge(
wac *whatsapp.Conn,
db Database,
UserChatID uint32,
) *WhappBridge {
return &WhappBridge{
wac: wac,
db: db,
UserChatID: UserChatID,
}
}
type WhappBridge struct {
wac *whatsapp.Conn
db Database
UserChatID uint32
}
func (b *WhappBridge) Accepts(c *deltachat.Chat, m *deltachat.Message) bool {
chatID := c.GetID()
chatJID, err := b.db.GetWhappJIDForDCID(chatID)
if err != nil {
// The database is failing, time to die :(
log.Fatal(err)
}
return chatJID != nil
}
func (b *WhappBridge) Execute(
c *deltachat.Context,
chat *deltachat.Chat,
m *deltachat.Message,
) {
JID, err := b.db.GetWhappJIDForDCID(chat.GetID())
if err != nil {
c.SendTextMessage(
b.UserChatID,
fmt.Sprintf(
"Whapp bridge dying: %s",
err.Error(),
),
)
log.Fatal(err)
}
text := whatsapp.TextMessage{
Info: whatsapp.MessageInfo{
RemoteJid: *JID,
},
Text: m.GetText(),
}
_, err = b.wac.Send(text)
if err != nil {
c.SendTextMessage(
b.UserChatID,
fmt.Sprintf(
"Error sending message to %s. Message contents: %s",
JID,
m.GetText(),
),
)
}
}

@ -0,0 +1,138 @@
package main
import (
"encoding/binary"
"go.etcd.io/bbolt"
)
type Database struct {
db *bbolt.DB
dbPath string
}
const (
JID_TO_DCID_INT uint8 = iota
DCID_TO_JID_INT
KEY_VALUE_INT
)
var (
JID_TO_DCID = []byte{JID_TO_DCID_INT}
DCID_TO_JID = []byte{DCID_TO_JID_INT}
KEY_VALUE = []byte{KEY_VALUE_INT}
)
func (d *Database) Init() error {
db, err := bbolt.Open(d.dbPath, 0600, nil)
if err != nil {
return err
}
err = db.Update(func(tx *bbolt.Tx) error {
_, err = tx.CreateBucketIfNotExists(JID_TO_DCID)
if err != nil {
return err
}
_, err = tx.CreateBucketIfNotExists(DCID_TO_JID)
if err != nil {
return err
}
_, err = tx.CreateBucketIfNotExists(KEY_VALUE)
return err
})
d.db = db
return nil
}
func (d *Database) GetDCIDForWhappJID(JID string) (*uint32, error) {
var DCID *uint32
err := d.db.View(func(tx *bbolt.Tx) error {
rawDCID := tx.Bucket(JID_TO_DCID).Get([]byte(JID))
if rawDCID == nil {
DCID = nil
} else {
i := binary.LittleEndian.Uint32(rawDCID)
DCID = &i
}
return nil
})
return DCID, err
}
func (d *Database) GetWhappJIDForDCID(DCID uint32) (*string, error) {
var JID *string
rawDCID := make([]byte, 4)
binary.LittleEndian.PutUint32(rawDCID, DCID)
err := d.db.View(func(tx *bbolt.Tx) error {
rawJID := tx.Bucket(DCID_TO_JID).Get(rawDCID)
if rawJID == nil {
JID = nil
} else {
str := string(rawJID)
JID = &str
}
return nil
})
return JID, err
}
func (d *Database) StoreDCIDForJID(JID string, DCID uint32) error {
err := d.db.Update(func(tx *bbolt.Tx) error {
DCIDbs := make([]byte, 4)
binary.LittleEndian.PutUint32(DCIDbs, DCID)
err := tx.Bucket(JID_TO_DCID).Put([]byte(JID), DCIDbs)
if err != nil {
return err
}
err = tx.Bucket(DCID_TO_JID).Put(DCIDbs, []byte(JID))
return err
})
return err
}
func (d *Database) Put(key []byte, value []byte) error {
err := d.db.Update(func(tx *bbolt.Tx) error {
err := tx.Bucket(KEY_VALUE).Put(key, value)
return err
})
return err
}
func (d *Database) Get(key []byte) []byte {
var value []byte
d.db.View(func(tx *bbolt.Tx) error {
value = tx.Bucket(KEY_VALUE).Get(key)
return nil
})
return value
}

@ -1,12 +1,13 @@
package main
import (
"errors"
"fmt"
"log"
"os"
"github.com/hugot/go-deltachat/deltabot"
"github.com/hugot/go-deltachat/deltachat"
"github.com/hugot/whapp-deltachat/botcommands"
"github.com/mdp/qrterminal"
)
func DcClientFromConfig(databasePath string, config map[string]string) *deltachat.Client {
@ -51,11 +52,75 @@ func BootstrapDcClientFromConfig(config Config) *deltachat.Client {
context.SendTextMessage(context.CreateChatByContactID(userID), "Whapp-Deltachat initialized")
bot := &deltabot.Bot{}
return dcClient
}
bot.AddCommand(&botcommands.Echo{})
// Add a user as verified contact to the deltachat context. This is necessary to be able
// to create verified groups.
func AddUserAsVerifiedContact(dcUserID uint32, client *deltachat.Client) (uint32, error) {
confirmChan := make(chan bool)
dcClient.On(deltachat.DC_EVENT_INCOMING_MSG, bot.HandleMessage)
client.On(
deltachat.DC_EVENT_SECUREJOIN_INVITER_PROGRESS,
func(c *deltachat.Context, e *deltachat.Event) {
contactIDInt, err := e.Data1.Int()
return dcClient
if err != nil {
log.Println(err)
// Something weird is going on here, deltachat is not passing expected
// values. Make the join process fail.
confirmChan <- false
return
}
contactID := uint32(*contactIDInt)
if contactID != dcUserID {
log.Println(
fmt.Sprintf(
"Unexpected contact ID encountered for securejoin progress: %v",
contactID,
),
)
return
}
progress, err := e.Data2.Int()
if err != nil {
log.Println(err)
confirmChan <- false
return
}
if *progress == 1000 {
confirmChan <- true
}
},
)
ctx := client.Context()
chatID := ctx.CreateGroupChat(true, "Whapp-DC ***status***")
log.Println("Scan this qr code with your DC client")
qrterminal.Generate(
ctx.GetSecurejoinQR(chatID),
qrterminal.L,
os.Stdout,
)
success := <-confirmChan
if !success {
return chatID, errors.New("Contact Verification process failed")
}
log.Println("Securejoin verification completed")
return chatID, nil
}

@ -3,7 +3,22 @@ module github.com/hugot/whapp-deltachat
go 1.13
require (
9fans.net/go v0.0.2 // indirect
github.com/Rhymen/go-whatsapp v0.1.0
github.com/dougm/goflymake v0.0.0-20140731161037-3b9634ef394a // indirect
github.com/golang/protobuf v1.3.2 // indirect
github.com/gorilla/websocket v1.4.1 // indirect
github.com/hugot/go-deltachat v0.0.0-20200103100028-e93f1f3d8b97
github.com/mdp/qrterminal v1.0.1
github.com/mdp/qrterminal/v3 v3.0.0 // indirect
github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836 // indirect
github.com/rogpeppe/godef v1.1.1 // indirect
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086
go.etcd.io/bbolt v1.3.3
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 // indirect
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
golang.org/x/tools v0.0.0-20200103211127-7bda30096dc1 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
gopkg.in/yaml.v2 v2.2.2
)

@ -1,25 +1,64 @@
9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E=
9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY=
9fans.net/go v0.0.2 h1:RYM6lWITV8oADrwLfdzxmt8ucfW6UtP9v1jg4qAbqts=
9fans.net/go v0.0.2/go.mod h1:lfPdxjq9v8pVQXUMBCx5EO5oLXWQFlKRQgs1kEkjoIM=
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA=
github.com/Rhymen/go-whatsapp v0.1.0 h1:XTXhFIQ/fx9jKObUnUX2Q+nh58EyeHNhX7DniE8xeuA=
github.com/Rhymen/go-whatsapp v0.1.0/go.mod h1:xJSy+okeRjKkQEH/lEYrnekXB3PG33fqL0I6ncAkV50=
github.com/Rhymen/go-whatsapp/examples/echo v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:zgCiQtBtZ4P4gFWvwl9aashsdwOcbb/EHOGRmSzM8ME=
github.com/Rhymen/go-whatsapp/examples/restoreSession v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:5sCUSpG616ZoSJhlt9iBNI/KXBqrVLcNUJqg7J9+8pU=
github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:RdiyhanVEGXTam+mZ3k6Y3VDCCvXYCwReOoxGozqhHw=
github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:suwzklatySS3Q0+NCxCDh5hYfgXdQUWU1DNcxwAxStM=
github.com/cheggaaa/pb v1.0.25/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dougm/goflymake v0.0.0-20140731161037-3b9634ef394a h1:S4+OSVOtl5a40p2ZgV7rA6YLl0wcjehR2jQVyWK1/UE=
github.com/dougm/goflymake v0.0.0-20140731161037-3b9634ef394a/go.mod h1:5K1XZIXX56t7gg4jDBoVXBH9ABugPa830vLJiD/XPHI=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kvannotten/pcd v0.6.1/go.mod h1:7T/uPMn1rNucUEPEWtuwJIOBjqB+GBYg+tS5aEURXXs=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mdp/qrterminal v1.0.1 h1:07+fzVDlPuBlXS8tB0ktTAyf+Lp1j2+2zK3fBOL5b7c=
github.com/mdp/qrterminal v1.0.1/go.mod h1:Z33WhxQe9B6CdW37HaVqcRKzP+kByF3q/qLxOGe12xQ=
github.com/mdp/qrterminal/v3 v3.0.0 h1:ywQqLRBXWTktytQNDKFjhAvoGkLVN3J2tAFZ0kMd9xQ=
github.com/mdp/qrterminal/v3 v3.0.0/go.mod h1:NJpfAs7OAm77Dy8EkWrtE4aq+cE6McoLXlBqXQEwvE0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836 h1:oc3CL18CoGhyOQJ7HDa9gJAde33bwI8Vi28zLdIzJVc=
github.com/nsf/gocode v0.0.0-20190302080247-5bee97b48836/go.mod h1:6Q8/OMaaKAgTX7/jt2bOXVDrm1eJhoNd+iwzghR7jvs=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/godef v1.1.1 h1:NujOtt9q9vIClRTB3sCZpavac+NMRaIayzrcz1h4fSE=
github.com/rogpeppe/godef v1.1.1/go.mod h1:oEo1eMy1VUEHUzUIX4F7IqvMJRiz9UId44mvnR8oPlQ=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 h1:RYiqpb2ii2Z6J4x0wxK46kvPBbFuZcdhS+CIztmYgZs=
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@ -31,13 +70,43 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181130195746-895048a75ecf/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20200103211127-7bda30096dc1 h1:NdJXeSjUw9JgihCnQeXjdsCFXq0n4I0Kv8wrEiQYZXU=
golang.org/x/tools v0.0.0-20200103211127-7bda30096dc1/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=

@ -1,10 +1,16 @@
package main
import (
"encoding/binary"
"fmt"
"log"
"os"
"os/signal"
"github.com/Rhymen/go-whatsapp"
"github.com/hugot/go-deltachat/deltabot"
"github.com/hugot/go-deltachat/deltachat"
"github.com/hugot/whapp-deltachat/botcommands"
)
func main() {
@ -23,13 +29,82 @@ func main() {
log.Fatal(err)
}
err = ensureDirectory(config.App.DataFolder)
ensureDirectoryOrDie(config.App.DataFolder)
ensureDirectoryOrDie(config.App.DataFolder + "/tmp")
dcClient := BootstrapDcClientFromConfig(*config)
// Give dc an opportunity to perform some close-down logic
// and close it's db etc.
defer dcClient.Close()
db := &Database{
dbPath: config.App.DataFolder + "/app.db",
}
err = db.Init()
if err != nil {
log.Fatal(err)
}
dcClient := BootstrapDcClientFromConfig(*config)
ctx := dcClient.Context()
userName := "user"
dcUserID := ctx.CreateContact(&userName, &config.App.UserAddress)
userChatIDRaw := db.Get([]byte("user-chat-id"))
var userChatID uint32
if userChatIDRaw == nil {
userChatID, err = AddUserAsVerifiedContact(dcUserID, dcClient)
if err != nil {
log.Fatal(err)
}
} else {
userChatID = binary.LittleEndian.Uint32(userChatIDRaw)
}
userChatIDbs := make([]byte, 4)
binary.LittleEndian.PutUint32(userChatIDbs, userChatID)
err = db.Put([]byte("user-chat-id"), userChatIDbs)
if err != nil {
log.Fatal(err)
}
var wac *whatsapp.Conn
for i := 0; i < 10; i++ {
wac, err = CreateAndLoginWhappConnection(
config.App.DataFolder,
dcClient.Context(),
dcUserID,
)
if err == nil {
break
}
}
if err != nil {
log.Fatal(err)
}
wac.AddHandler(&WhappHandler{
dcContext: dcClient.Context(),
db: db,
dcUserID: dcUserID,
wac: wac,
})
bot := &deltabot.Bot{}
bot.AddCommand(&botcommands.Echo{})
bot.AddCommand(botcommands.NewWhappBridge(
wac, db, dcClient.Context().GetChatIDByContactID(dcUserID),
))
dcClient.On(deltachat.DC_EVENT_INCOMING_MSG, bot.HandleMessage)
wait := make(chan os.Signal, 1)
signal.Notify(wait, os.Interrupt)
@ -38,10 +113,6 @@ func main() {
select {
case sig := <-wait:
log.Println(sig)
// Give dc an opportunity to perform some close-down logic
// and close it's db etc.
dcClient.Close()
return
}
}
@ -64,3 +135,11 @@ func ensureDirectory(dir string) error {
return nil
}
func ensureDirectoryOrDie(dir string) {
err := ensureDirectory(dir)
if err != nil {
log.Fatal(err)
}
}

@ -0,0 +1,81 @@
package main
import (
"fmt"
"log"
"github.com/Rhymen/go-whatsapp"
"github.com/hugot/go-deltachat/deltachat"
)
type WhappHandler struct {
dcContext *deltachat.Context
db *Database
dcUserID uint32
wac *whatsapp.Conn
}
// Find or create a deltachat verified group chat for a whatsapp JID and return it's ID.
func (h *WhappHandler) getOrCreateDCIDForJID(JID string, isGroup bool) (uint32, error) {
if DCID, _ := h.db.GetDCIDForWhappJID(JID); DCID != nil {
return *DCID, nil
}
chatName := JID
if isGroup {
chat, ok := h.wac.Store.Chats[JID]
if ok {
chatName = chat.Name
}
} else {
contact, ok := h.wac.Store.Contacts[JID]
if ok {
chatName = contact.Name
}
}
DCID := h.dcContext.CreateGroupChat(true, chatName)
err := h.db.StoreDCIDForJID(JID, DCID)
if err != nil {
return DCID, err
}
h.dcContext.AddContactToChat(DCID, h.dcUserID)
return DCID, err
}
func (h *WhappHandler) HandleError(err error) {
log.Println("Whatsapp Error: " + err.Error())
}
func (h *WhappHandler) HandleTextMessage(m whatsapp.TextMessage) {
JID := m.Info.RemoteJid
DCID, err := h.getOrCreateDCIDForJID(JID, m.Info.RemoteJid != m.Info.SenderJid)
if err != nil {
log.Println(err)
chatID := h.dcContext.GetChatIDByContactID(h.dcUserID)
h.dcContext.SendTextMessage(
chatID,
err.Error(),
)
}
senderName := m.Info.SenderJid
contact, ok := h.wac.Store.Contacts[m.Info.SenderJid]
if ok {
senderName = contact.Name
}
h.dcContext.SendTextMessage(
DCID,
fmt.Sprintf("%s:\n%s", senderName, m.Text),
)
}

@ -0,0 +1,111 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"mime"
"os"
"time"
"github.com/Rhymen/go-whatsapp"
"github.com/hugot/go-deltachat/deltachat"
"github.com/skip2/go-qrcode"
)
func CreateAndLoginWhappConnection(
storageDir string,
dcContext *deltachat.Context,
dcUserID uint32,
) (*whatsapp.Conn, error) {
wac, err := whatsapp.NewConn(20 * time.Second)
if err != nil {
return wac, err
}
var session whatsapp.Session
sessionFile := storageDir + "/whapp-session.json"
if _, err := os.Stat(sessionFile); os.IsNotExist(err) {
session, err = WhappQrLogin(storageDir, wac, dcContext, dcUserID)
if err != nil {
return wac, err
}
} else {
session = whatsapp.Session{}
sessionJson, err := ioutil.ReadFile(sessionFile)
err = json.Unmarshal(sessionJson, &session)
if err != nil {
return wac, err
}
session, err = wac.RestoreWithSession(session)
if err != nil {
return wac, err
}
}
err = StoreWhappSession(session, storageDir)
return wac, err
}
func WhappQrLogin(
storageDir string,
wac *whatsapp.Conn,
dcContext *deltachat.Context,
dcUserID uint32,
) (whatsapp.Session, error) {
qrChan := make(chan string)
go func() {
qrCode := <-qrChan
tmpFile, err := ioutil.TempFile(storageDir+"/tmp", "qr")
if err != nil {
log.Fatal(err)
}
err = qrcode.WriteFile(qrCode, qrcode.Medium, 256, tmpFile.Name())
if err != nil {
log.Fatal(err)
}
message := dcContext.NewMessage(deltachat.DC_MSG_IMAGE)
log.Println("MIME: " + mime.TypeByExtension("png"))
message.SetFile(tmpFile.Name(), "image/png")
message.SetText("Scan this QR code from whatsapp")
dcContext.SendMessage(
dcContext.GetChatIDByContactID(dcUserID),
message,
)
}()
session, err := wac.Login(qrChan)
return session, err
}
func StoreWhappSession(session whatsapp.Session, storageDir string) error {
sessionJson, err := json.Marshal(session)
if err != nil {
return err
}
err = ioutil.WriteFile(storageDir+"/whapp-session.json", sessionJson, 0600)
return err
}
Loading…
Cancel
Save