This does not do anything useful just yet. It will be hooked to access control checks later on. Wildcards are converted to regular expressions, because it was simpler to do that than to write (or include) some ugly wildcard matcher library. It also provides more flexibility, should we wish to use it later. Regular expressions should also work well performance-wise. We compile wildcards to regexes early on (during configuration processing) and fail if we detect a bad pattern. This is meant to catch various problems (typos or other mistakes) that could happen. For this to work, configuration building had to be redone, since it can now return an error. This may be useful in the future for validating other configuration settings. Related to https://gitlab.com/etke.cc/postmoogle/-/issues/1
132 lines
2.8 KiB
Go
132 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/getsentry/sentry-go"
|
|
_ "github.com/lib/pq"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
"gitlab.com/etke.cc/go/logger"
|
|
"gitlab.com/etke.cc/linkpearl"
|
|
lpcfg "gitlab.com/etke.cc/linkpearl/config"
|
|
|
|
"gitlab.com/etke.cc/postmoogle/bot"
|
|
"gitlab.com/etke.cc/postmoogle/config"
|
|
"gitlab.com/etke.cc/postmoogle/smtp"
|
|
)
|
|
|
|
var (
|
|
mxb *bot.Bot
|
|
log *logger.Logger
|
|
)
|
|
|
|
func main() {
|
|
quit := make(chan struct{})
|
|
|
|
cfg, err := config.New()
|
|
if err != nil {
|
|
log = logger.New("postmoogle.", "info")
|
|
log.Fatal("%s", err)
|
|
}
|
|
|
|
log = logger.New("postmoogle.", cfg.LogLevel)
|
|
|
|
log.Info("#############################")
|
|
log.Info("Postmoogle")
|
|
log.Info("Matrix: true")
|
|
log.Info("#############################")
|
|
|
|
log.Debug("starting internal components...")
|
|
initSentry(cfg)
|
|
initBot(cfg)
|
|
initShutdown(quit)
|
|
defer recovery()
|
|
|
|
go startBot(cfg.StatusMsg)
|
|
if err := smtp.Start(cfg.Domain, cfg.Port, cfg.LogLevel, cfg.MaxSize, mxb); err != nil {
|
|
//nolint:gocritic
|
|
log.Fatal("SMTP server crashed: %v", err)
|
|
}
|
|
|
|
<-quit
|
|
}
|
|
|
|
func initSentry(cfg *config.Config) {
|
|
err := sentry.Init(sentry.ClientOptions{
|
|
Dsn: cfg.Sentry.DSN,
|
|
AttachStacktrace: true,
|
|
})
|
|
if err != nil {
|
|
log.Fatal("cannot initialize sentry: %v", err)
|
|
}
|
|
}
|
|
|
|
func initBot(cfg *config.Config) {
|
|
db, err := sql.Open(cfg.DB.Dialect, cfg.DB.DSN)
|
|
if err != nil {
|
|
log.Fatal("cannot initialize SQL database: %v", err)
|
|
}
|
|
mxlog := logger.New("matrix.", cfg.LogLevel)
|
|
lp, err := linkpearl.New(&lpcfg.Config{
|
|
Homeserver: cfg.Homeserver,
|
|
Login: cfg.Login,
|
|
Password: cfg.Password,
|
|
DB: db,
|
|
Dialect: cfg.DB.Dialect,
|
|
NoEncryption: cfg.NoEncryption,
|
|
LPLogger: mxlog,
|
|
APILogger: logger.New("api.", cfg.LogLevel),
|
|
StoreLogger: logger.New("store.", cfg.LogLevel),
|
|
CryptoLogger: logger.New("olm.", cfg.LogLevel),
|
|
})
|
|
if err != nil {
|
|
// nolint // Fatal = panic, not os.Exit()
|
|
log.Fatal("cannot initialize matrix bot: %v", err)
|
|
}
|
|
mxb = bot.New(lp, mxlog, cfg.Prefix, cfg.Domain, cfg.NoOwner, cfg.Federation, cfg.Users)
|
|
log.Debug("bot has been created")
|
|
}
|
|
|
|
func initShutdown(quit chan struct{}) {
|
|
listener := make(chan os.Signal, 1)
|
|
signal.Notify(listener, os.Interrupt, syscall.SIGABRT, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
<-listener
|
|
defer close(quit)
|
|
|
|
shutdown()
|
|
}()
|
|
}
|
|
|
|
func startBot(statusMsg string) {
|
|
log.Debug("starting matrix bot: %s...", statusMsg)
|
|
err := mxb.Start(statusMsg)
|
|
if err != nil {
|
|
//nolint:gocritic
|
|
log.Fatal("cannot start the bot: %v", err)
|
|
}
|
|
}
|
|
|
|
func shutdown() {
|
|
log.Info("Shutting down...")
|
|
mxb.Stop()
|
|
|
|
sentry.Flush(5 * time.Second)
|
|
log.Info("Postmoogle has been stopped")
|
|
os.Exit(0)
|
|
}
|
|
|
|
func recovery() {
|
|
defer shutdown()
|
|
err := recover()
|
|
// no problem just shutdown
|
|
if err == nil {
|
|
sentry.CurrentHub().Recover(err)
|
|
}
|
|
}
|