Initial config structs and example config, some whatsapp testing
This commit is contained in:
		
							
								
								
									
										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() { | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user