Initial config structs and example config, some whatsapp testing
This commit is contained in:
parent
c84b5dd5dc
commit
ace08205d9
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
.idea
|
.idea
|
||||||
|
*.session
|
||||||
|
76
config/bridge.go
Normal file
76
config/bridge.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// mautrix-whatsapp - A Matrix-Whatsapp puppeting bridge.
|
||||||
|
// Copyright (C) 2018 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BridgeConfig struct {
|
||||||
|
RawUsernameTemplate string `yaml:"username_template"`
|
||||||
|
RawDisplaynameTemplate string `yaml:"displayname_template"`
|
||||||
|
UsernameTemplate *template.Template `yaml:"-"`
|
||||||
|
DisplaynameTemplate *template.Template `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc BridgeConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
err := unmarshal(bc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.UsernameTemplate, err = template.New("username").Parse(bc.RawUsernameTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.DisplaynameTemplate, err = template.New("displayname").Parse(bc.RawDisplaynameTemplate)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplaynameTemplateArgs struct {
|
||||||
|
Displayname string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UsernameTemplateArgs struct {
|
||||||
|
Receiver string
|
||||||
|
UserID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc BridgeConfig) FormatDisplayname(displayname string) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
bc.DisplaynameTemplate.Execute(&buf, DisplaynameTemplateArgs{
|
||||||
|
Displayname: displayname,
|
||||||
|
})
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc BridgeConfig) FormatUsername(receiver, userID string) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
bc.UsernameTemplate.Execute(&buf, UsernameTemplateArgs{
|
||||||
|
Receiver: receiver,
|
||||||
|
UserID: userID,
|
||||||
|
})
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc BridgeConfig) MarshalYAML() (interface{}, error) {
|
||||||
|
bc.RawDisplaynameTemplate = bc.FormatDisplayname("{{.Displayname}}")
|
||||||
|
bc.RawUsernameTemplate = bc.FormatUsername("{{.Receiver}}", "{{.UserID}}")
|
||||||
|
return bc, nil
|
||||||
|
}
|
81
config/config.go
Normal file
81
config/config.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// mautrix-whatsapp - A Matrix-Whatsapp puppeting bridge.
|
||||||
|
// Copyright (C) 2018 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"maunium.net/go/mautrix-appservice"
|
||||||
|
"io/ioutil"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Homeserver struct {
|
||||||
|
Address string `yaml:"address"`
|
||||||
|
Domain string `yaml:"domain"`
|
||||||
|
} `yaml:"homeserver"`
|
||||||
|
|
||||||
|
AppService struct {
|
||||||
|
Address string `yaml:"address"`
|
||||||
|
Hostname string `yaml:"hostname"`
|
||||||
|
Port uint16 `yaml:"port"`
|
||||||
|
|
||||||
|
Database string `yaml:"database"`
|
||||||
|
|
||||||
|
ID string `yaml:"id"`
|
||||||
|
Bot struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Displayname string `yaml:"displayname"`
|
||||||
|
Avatar string `yaml:"avatar"`
|
||||||
|
} `yaml:"bot"`
|
||||||
|
|
||||||
|
ASToken string `yaml:"as_token"`
|
||||||
|
HSToken string `yaml:"hs_token"`
|
||||||
|
} `yaml:"appservice"`
|
||||||
|
|
||||||
|
Bridge BridgeConfig `yaml:"bridge"`
|
||||||
|
|
||||||
|
Logging appservice.LogConfig `yaml:"logging"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load(path string) (*Config, error) {
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = &Config{}
|
||||||
|
err = yaml.Unmarshal(data, config)
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *Config) Save(path string) error {
|
||||||
|
data, err := yaml.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(path, data, 0600)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *Config) Appservice() (*appservice.Config, error) {
|
||||||
|
as := appservice.Create()
|
||||||
|
as.LogConfig = config.Logging
|
||||||
|
as.HomeserverDomain = config.Homeserver.Domain
|
||||||
|
as.HomeserverURL = config.Homeserver.Address
|
||||||
|
var err error
|
||||||
|
as.Registration, err = config.GetRegistration()
|
||||||
|
return as, err
|
||||||
|
}
|
62
config/registration.go
Normal file
62
config/registration.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// mautrix-whatsapp - A Matrix-Whatsapp puppeting bridge.
|
||||||
|
// Copyright (C) 2018 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 config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"maunium.net/go/mautrix-appservice"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (config *Config) NewRegistration() (*appservice.Registration, error) {
|
||||||
|
registration := appservice.CreateRegistration("mautrix-whatsapp")
|
||||||
|
|
||||||
|
err := config.copyToRegistration(registration)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.AppService.ASToken = registration.AppToken
|
||||||
|
config.AppService.HSToken = registration.ServerToken
|
||||||
|
return registration, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *Config) GetRegistration() (*appservice.Registration, error) {
|
||||||
|
registration := appservice.CreateRegistration("mautrix-whatsapp")
|
||||||
|
|
||||||
|
err := config.copyToRegistration(registration)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
registration.AppToken = config.AppService.ASToken
|
||||||
|
registration.ServerToken = config.AppService.HSToken
|
||||||
|
return registration, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *Config) copyToRegistration(registration *appservice.Registration) error {
|
||||||
|
registration.ID = config.AppService.ID
|
||||||
|
registration.URL = config.AppService.Address
|
||||||
|
registration.RateLimited = false
|
||||||
|
registration.SenderLocalpart = config.AppService.Bot.Username
|
||||||
|
|
||||||
|
userIDRegex, err := regexp.Compile(config.Bridge.FormatUsername("[0-9]+", "[0-9]+"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registration.Namespaces.RegisterUserIDs(userIDRegex, true)
|
||||||
|
return nil
|
||||||
|
}
|
60
example-config.yaml
Normal file
60
example-config.yaml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Homeserver details.
|
||||||
|
homeserver:
|
||||||
|
# The address that this appservice can use to connect to the homeserver.
|
||||||
|
address: https://matrix.org
|
||||||
|
# The domain of the homeserver (for MXIDs, etc).
|
||||||
|
domain: matrix.org
|
||||||
|
|
||||||
|
# Application service host/registration related details.
|
||||||
|
# Changing these values requires regeneration of the registration.
|
||||||
|
appservice:
|
||||||
|
# The address that the homeserver can use to connect to this appservice.
|
||||||
|
address: http://localhost:8080
|
||||||
|
|
||||||
|
# The hostname and port where this appservice should listen.
|
||||||
|
hostname: 0.0.0.0
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
# The full URI to the database. Only SQLite is currently supported.
|
||||||
|
database: sqlite:///mautrix-whatsapp.db
|
||||||
|
|
||||||
|
# The unique ID of this appservice.
|
||||||
|
id: whatsapp
|
||||||
|
# Appservice bot details.
|
||||||
|
bot:
|
||||||
|
# Username of the appservice bot.
|
||||||
|
username: whatsappbot
|
||||||
|
# Display name and avatar for bot. Set to "remove" to remove display name/avatar, leave empty
|
||||||
|
# to leave display name/avatar as-is.
|
||||||
|
displayname: WhatsApp bridge bot
|
||||||
|
avatar: mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr
|
||||||
|
|
||||||
|
# Authentication tokens for AS <-> HS communication. Autogenerated; do not modify.
|
||||||
|
as_token: "This value is generated when generating the registration"
|
||||||
|
hs_token: "This value is generated when generating the registration"
|
||||||
|
|
||||||
|
# Bridge config. Currently unused.
|
||||||
|
bridge:
|
||||||
|
# Localpart template of MXIDs for Whatsapp users.
|
||||||
|
# {{.receiver}} is replaced with the Whatsapp user ID of the Matrix user receiving messages.
|
||||||
|
# {{.userid}} is replaced with the user ID of the Whatsapp user.
|
||||||
|
username_template: "whatsapp_{{.Receiver}}_{{.UserID}}"
|
||||||
|
# Displayname template for Whatsapp users.
|
||||||
|
# {{.displayname}} is replaced with the display name of the Whatsapp user.
|
||||||
|
displayname_template: "{{.Displayname}}"
|
||||||
|
|
||||||
|
# Logging config.
|
||||||
|
logging:
|
||||||
|
# The directory for log files. Will be created if not found.
|
||||||
|
directory: ./logs
|
||||||
|
# Available variables: .date for the file date and .index for different log files on the same day.
|
||||||
|
file_name_format: {{.date}}-{{.index}.log
|
||||||
|
# Date format for file names in the Go time format: https://golang.org/pkg/time/#pkg-constants
|
||||||
|
file_date_format: 2006-01-02
|
||||||
|
# Log file permissions.
|
||||||
|
file_mode: 0600
|
||||||
|
# Timestamp format for log entries in the Go time format.
|
||||||
|
timestamp_format: Jan _2, 2006 15:04:05
|
||||||
|
# Minimum severity for log messages.
|
||||||
|
# Options: debug, info, warn, error, fatal
|
||||||
|
print_level: info
|
97
main.go
97
main.go
@ -1,4 +1,4 @@
|
|||||||
// mautrix-whatsapp - A puppeting Matrix-Whatsapp bridge.
|
// mautrix-whatsapp - A Matrix-Whatsapp puppeting bridge.
|
||||||
// Copyright (C) 2018 Tulir Asokan
|
// Copyright (C) 2018 Tulir Asokan
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
@ -16,6 +16,99 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Rhymen/go-whatsapp"
|
||||||
|
"time"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"bufio"
|
||||||
|
"encoding/gob"
|
||||||
|
"github.com/mdp/qrterminal"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
wac, err := whatsapp.NewConn(20 * time.Second)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wac.AddHandler(myHandler{})
|
||||||
|
|
||||||
|
sess, err := LoadSession("whatsapp.session")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
sess, err = Login(wac)
|
||||||
|
} else {
|
||||||
|
sess, err = wac.RestoreSession(sess)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
SaveSession(sess, "whatsapp.session")
|
||||||
|
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
for {
|
||||||
|
fmt.Print("receiver> ")
|
||||||
|
receiver, _ := reader.ReadString('\n')
|
||||||
|
fmt.Print("message> ")
|
||||||
|
message, _ := reader.ReadString('\n')
|
||||||
|
wac.Send(whatsapp.TextMessage{
|
||||||
|
Info: whatsapp.MessageInfo{
|
||||||
|
RemoteJid: fmt.Sprintf("%s@s.whatsapp.net", receiver),
|
||||||
|
},
|
||||||
|
Text: message,
|
||||||
|
})
|
||||||
|
fmt.Println(receiver, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Login(wac *whatsapp.Conn) (whatsapp.Session, error) {
|
||||||
|
qrChan := make(chan string)
|
||||||
|
go func() {
|
||||||
|
qrterminal.Generate(<-qrChan, qrterminal.L, os.Stdout)
|
||||||
|
}()
|
||||||
|
return wac.Login(qrChan)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SaveSession(session whatsapp.Session, fileName string) {
|
||||||
|
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := gob.NewEncoder(file)
|
||||||
|
enc.Encode(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSession(fileName string) (sess whatsapp.Session, err error) {
|
||||||
|
file, err := os.OpenFile(fileName, os.O_RDONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return sess, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dec := gob.NewDecoder(file)
|
||||||
|
dec.Decode(sess)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type myHandler struct{}
|
||||||
|
|
||||||
|
func (myHandler) HandleError(err error) {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (myHandler) HandleTextMessage(message whatsapp.TextMessage) {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (myHandler) HandleImageMessage(message whatsapp.ImageMessage) {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (myHandler) HandleVideoMessage(message whatsapp.VideoMessage) {
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (myHandler) HandleJsonMessage(message string) {
|
||||||
|
fmt.Println(message)
|
||||||
}
|
}
|
||||||
|
21
matrix.go
Normal file
21
matrix.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// mautrix-whatsapp - A Matrix-Whatsapp puppeting bridge.
|
||||||
|
// Copyright (C) 2018 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 main
|
||||||
|
|
||||||
|
func InitMatrix() {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user