// Copyright (C) 2024 Leah Neukirchen // // based on mautrix-go example code: // // Copyright (C) 2017 Tulir Asokan // Copyright (C) 2018-2020 Luca Weiss // Copyright (C) 2023 Tulir Asokan // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. package main import ( "context" "errors" "flag" "os" "os/signal" "strings" "time" "k8s.io/klog" "maunium.net/go/mautrix" "maunium.net/go/mautrix/id" ) var ( flagMatrixHomeserver = "matrix.org" flagMatrixUsername = "@fafomo:matrix.org" flagMatrixPasswordFile = "password.txt" flagPresenceMatrixRoom string flagPresenceBackendURL string flagStreamMatrixRoom string ) func main() { flag.StringVar(&flagMatrixHomeserver, "matrix_homeserver", flagMatrixHomeserver, "Address of Matrix homeserver") flag.StringVar(&flagMatrixUsername, "matrix_username", flagMatrixUsername, "Matrix login username") flag.StringVar(&flagMatrixPasswordFile, "matrix_password_file", flagMatrixPasswordFile, "Path to file containing matrix login password") flag.StringVar(&flagPresenceMatrixRoom, "presence_matrix_room", flagPresenceMatrixRoom, "Matrix room MXID") flag.StringVar(&flagPresenceBackendURL, "presence_backend_url", flagPresenceBackendURL, "Checkinator (backend) addresss") flag.StringVar(&flagStreamMatrixRoom, "stream_matrix_room", flagStreamMatrixRoom, "Matrix room MXID") flag.Parse() for _, s := range []struct { value string name string }{ {flagMatrixHomeserver, "matrix_homeserver"}, {flagMatrixUsername, "matrix_username"}, {flagMatrixPasswordFile, "matrix_password_file"}, } { if s.value == "" { klog.Exitf("-%s must be set", s.name) } } startCtx, startCtxC := context.WithTimeout(context.Background(), 20*time.Second) defer startCtxC() client, err := mautrix.NewClient(flagMatrixHomeserver, id.UserID(flagMatrixUsername), "") if err != nil { klog.Exitf("NewClient failed: %v", err) } passwordBytes, err := os.ReadFile(flagMatrixPasswordFile) if err != nil { klog.Exitf("Could not read password file: %v", err) } password := strings.TrimSpace(string(passwordBytes)) klog.Infof("Logging in...") login, err := client.Login(startCtx, &mautrix.ReqLogin{ Type: mautrix.AuthTypePassword, Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: flagMatrixUsername}, Password: password, }) if err != nil { klog.Exitf("Failed to log in: %v", err) } client.AccessToken = login.AccessToken klog.Infof("Now running...") ctx, ctxC := signal.NotifyContext(context.Background(), os.Interrupt) defer ctxC() // Run Matrix sync process in the background. syncDone := make(chan struct{}) go func() { err := client.SyncWithContext(ctx) defer close(syncDone) if err != nil && !errors.Is(err, ctx.Err()) { klog.Exitf("Sync failed: %v", err) } }() if flagPresenceMatrixRoom != "" || flagPresenceBackendURL != "" { if flagPresenceMatrixRoom == "" || flagPresenceBackendURL == "" { klog.Exitf("If presence_matrix_room is set, presence_backend_url must be set (and vice versa)") } klog.Infof("Starting presence module.") go presence(ctx, client) } else { klog.Infof("NOT starting presence module.") } if flagStreamMatrixRoom != "" { klog.Infof("Starting streaming module.") go streaming(ctx, client) } else { klog.Infof("NOT starting streaming module.") } <-ctx.Done() klog.Infof("Waiting for graceful sync before exiting...") <-syncDone klog.Infof("Done.") }