// package main is the main package for the LapisDeploy program package main import ( "context" "log" "time" "strings" "fmt" "maunium.net/go/mautrix" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" "maunium.net/go/mautrix/format" ) // MatrixMessage stores information about a matrix message. type MatrixMessage struct { text string } // MatrixCommand stores information about a matrix chat command type MatrixCommand struct { cmd string callback func(ctx context.Context, evt *event.Event) string description string } // Output queue var MatrixOut []MatrixMessage // ChatCommands var Chatcommands []MatrixCommand // sendMessage sends a message through Matrix func sendMessage(msg MatrixMessage) { MatrixOut = append(MatrixOut, msg) } // registerChatCommand func registerChatCommand(cmd string, description string, callback func(ctx context.Context, evt *event.Event) string) { Chatcommands = append(Chatcommands, MatrixCommand{ cmd: cmd, callback: callback, description: description, }) } // initMatrix starts a Matrix bot. func initMatrix() { client, err := mautrix.NewClient(configuration.matrix.homeserver, "", "") if err != nil { log.Fatal(err) } resp, err := client.Login(context.Background(), &mautrix.ReqLogin{ Type: "m.login.password", Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: configuration.matrix.username}, Password: configuration.matrix.password, StoreCredentials: true, }) if err != nil { log.Panic(err) } log.Printf("[Matrix] Logged in as %s", resp.UserID) syncer := client.Syncer.(*mautrix.DefaultSyncer) client.Syncer.(mautrix.ExtensibleSyncer).OnSync(client.DontProcessOldEvents) syncer.OnEventType(event.StateMember, func(ctx context.Context, evt *event.Event) { if evt.GetStateKey() == client.UserID.String() && evt.Content.AsMember().Membership == event.MembershipInvite { if evt.RoomID.String() == configuration.matrix.room_id { _, err := client.JoinRoomByID(ctx, evt.RoomID) if err == nil { log.Printf("[Matrix] Joined room '%s' (Invited by '%s')", evt.RoomID.String(), evt.Sender.String()) } else { log.Printf("[Matrix] Failed to join room '%s' after invite (Invited by '%s')", evt.RoomID.String(), evt.Sender.String()) } } else { log.Printf("[Matrix] Rejected invite to room '%s' (Invited by '%s')", evt.RoomID.String(), evt.Sender.String()) } } }) syncer.OnEventType(event.EventMessage, func(ctx context.Context, evt *event.Event) { if evt.RoomID.String() == configuration.matrix.room_id { prefixes := []string{"!", configuration.matrix.username+" "} for _,prefix := range prefixes { if strings.HasPrefix(evt.Content.AsMessage().Body, prefix) { found_command := false for _, command := range Chatcommands { if command.cmd == strings.TrimPrefix(evt.Content.AsMessage().Body, prefix) { found_command = true out := command.callback(ctx, evt) content := format.RenderMarkdown(out, true, false) content.SetReply(evt) client.SendMessageEvent(ctx, evt.RoomID, event.EventMessage, content) } } if !found_command { client.SendText(ctx, evt.RoomID, "🔴 Command not found") } break } } } }) registerChatCommand("help", "Show the help dialouge", func(ctx context.Context, evt *event.Event) string { text := "" for _,cmd := range Chatcommands { text = fmt.Sprintf("%s- %s\n %s\n", text, cmd.cmd, cmd.description) } return text }) registerChatCommand("sites", "Display all available sites", func(ctx context.Context, evt *event.Event) string { text := "⚪️ Getting sites...\n" sites, err := getAllSites() if err.code != 0 { return text+"🔴 Failed to get sites!" } for _, site := range sites { text = fmt.Sprintf("%s- %s\n", text, site.name) } if len(sites) == 0 { text = text+"*No sites found*" } return text }) go func () { for range time.Tick(time.Second * 6) { log.Printf("Scanning for queued messages...") for _, msg := range MatrixOut { _, err := client.SendMessageEvent(context.Background(), id.RoomID(configuration.matrix.room_id), event.EventMessage, format.RenderMarkdown(msg.text, true, false)) if err != nil { log.Printf("[Matrix] ERROR : %s", err) continue } log.Print("[Matrix] Sent queued message successfully.") } MatrixOut = []MatrixMessage{} } }() go func() { log.Print("[Matrix] Running!") err = client.Sync() if err != nil { log.Fatal(err) } }() }