package main import ( "context" "crypto/rand" "encoding/hex" "encoding/json" "flag" "io/ioutil" "os" "os/signal" "syscall" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" ) type ConfigFile struct { LogLevel string `json:"log_level"` Registration string `json:"registration"` ASBindAddr string `json:"appservice_bind_addr"` Server string `json:"homeserver_url"` MatrixDomain string `json:"matrix_domain"` NameFormat string `json:"name_format"` WebBindAddr string `json:"web_bind_addr"` WebURL string `json:"web_url"` SessionKey string `json:"web_session_key"` DbType string `json:"db_type"` DbPath string `json:"db_path"` AvatarFile string `json:"easybridge_avatar"` } var configFlag = flag.String("config", "./config.json", "Configuration file path") var config *ConfigFile var registration *mxlib.Registration func readConfig() ConfigFile { defaultKey := make([]byte, 32) rand.Read(defaultKey) config_file := ConfigFile{ LogLevel: "info", ASBindAddr: "0.0.0.0:8321", WebBindAddr: "0.0.0.0:8281", Registration: "./registration.yaml", Server: "http://localhost:8008", NameFormat: "{}_ezbr_", DbType: "sqlite3", DbPath: "easybridge.db", AvatarFile: "./easybridge.jpg", SessionKey: hex.EncodeToString(defaultKey), } _, err := os.Stat(*configFlag) if os.IsNotExist(err) { // Generate default config file log.Printf("Generating default config file as %s", *configFlag) bytes, err := json.MarshalIndent(&config_file, "", " ") if err != nil { log.Fatal(err) } err = ioutil.WriteFile(*configFlag, bytes, 0644) if err != nil { log.Fatal(err) } return config_file } if err != nil { log.Fatal(err) } bytes, err := ioutil.ReadFile(*configFlag) if err != nil { log.Fatal(err) } err = json.Unmarshal(bytes, &config_file) if err != nil { log.Fatal(err) } return config_file } func readRegistration(file string) mxlib.Registration { rnd := make([]byte, 64) n, err := rand.Read(rnd) if err != nil || n != 64 { log.Fatal(err) } reg := mxlib.Registration{ Id: "Easybridge", Url: "http://localhost:8321", AsToken: hex.EncodeToString(rnd[:32]), HsToken: hex.EncodeToString(rnd[32:]), SenderLocalpart: "_ezbr_", RateLimited: false, Namespaces: mxlib.RegistrationNamespaceSet{ Users: []mxlib.RegistrationNamespace{ mxlib.RegistrationNamespace{ Exclusive: true, Regex: "@.*_ezbr_", }, }, Aliases: []mxlib.RegistrationNamespace{ mxlib.RegistrationNamespace{ Exclusive: true, Regex: "#.*_ezbr_", }, }, Rooms: []mxlib.RegistrationNamespace{}, }, } _, err = os.Stat(file) if os.IsNotExist(err) { // Generate default config file log.Printf("Generating default registration file as %s", file) bytes, err := yaml.Marshal(®) if err != nil { log.Fatal(err) } err = ioutil.WriteFile(file, bytes, 0644) if err != nil { log.Fatal(err) } return reg } if err != nil { log.Fatal(err) } bytes, err := ioutil.ReadFile(file) if err != nil { log.Fatal(err) } err = yaml.Unmarshal(bytes, ®) if err != nil { log.Fatal(err) } return reg } func main() { flag.Parse() // Read configuration config_file := readConfig() config = &config_file log_level, err := log.ParseLevel(config.LogLevel) if err != nil { log.Fatal(err) } log.SetLevel(log_level) reg_file := readRegistration(config.Registration) registration = ®_file // Create context and handlers for errors and signals ctx, stop_all := context.WithCancel(context.Background()) errch := make(chan error) sigch := make(chan os.Signal) signal.Notify(sigch, os.Interrupt, syscall.SIGTERM) defer func() { signal.Stop(sigch) stop_all() }() // Start appservice and web server _, err = StartAppService(errch, ctx) if err != nil { log.Fatal(err) } _ = StartWeb(errch, ctx) // Wait for an error somewhere or interrupt signal select { case err = <-errch: log.Error(err) stop_all() case sig := <-sigch: log.Warnf("Got signal: %s", sig.String()) stop_all() case <-ctx.Done(): } log.Info("Closing all account connections...") CloseAllAccountsForShutdown() log.Info("Exiting.") }