From 5f648254a575f0f4a61148903c930d53cebc447e Mon Sep 17 00:00:00 2001 From: Erik Winter Date: Mon, 15 May 2023 12:28:12 +0200 Subject: [PATCH] dockerfile --- .gitignore | 3 +- Dockerfile | 13 +++++ Makefile | 4 ++ go.mod | 1 + go.sum | 3 + main.go | 163 +++++++++++++++++++---------------------------------- 6 files changed, 80 insertions(+), 107 deletions(-) create mode 100644 Dockerfile create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 723ef36..a80ff4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.idea \ No newline at end of file +.idea +*.db \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1719cc0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.20-bullseye as build +RUN apt update && apt install -y libolm3 libolm-dev + +WORKDIR /src +COPY . ./ +RUN go mod download +RUN go build -o /matrix-bots ./main.go + +FROM debian:bullseye +RUN apt update && apt install -y libolm3 ca-certificates openssl + +COPY --from=build /matrix-bots /matrix-bots +CMD /matrix-bots \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..89553ca --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +docker-push: + docker build . -t matrix-bots + docker tag matrix-bots registry.ewintr.nl/matrix-bots + docker push registry.ewintr.nl/matrix-bots \ No newline at end of file diff --git a/go.mod b/go.mod index 2f8a01a..53fe0d5 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( github.com/chzyer/readline v1.5.1 + github.com/mattn/go-sqlite3 v1.14.16 github.com/rs/zerolog v1.29.1 github.com/sashabaranov/go-openai v1.9.4 golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea diff --git a/go.sum b/go.sum index 7426b27..70af2a6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= @@ -11,6 +12,8 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= diff --git a/main.go b/main.go index c9691d3..86e2699 100644 --- a/main.go +++ b/main.go @@ -5,10 +5,13 @@ import ( "errors" "fmt" "github.com/chzyer/readline" + _ "github.com/mattn/go-sqlite3" "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/sashabaranov/go-openai" "golang.org/x/exp/slog" "maunium.net/go/mautrix" + "maunium.net/go/mautrix/crypto/cryptohelper" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/format" "maunium.net/go/mautrix/id" @@ -19,83 +22,48 @@ import ( ) func main() { + logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) + MatrixHomeserver, ok := os.LookupEnv("MATRIX_HOMESERVER") if !ok { - slog.Error("MATRIX_HOME_SERVER is not set") + logger.Error("MATRIX_HOME_SERVER is not set!") os.Exit(1) } MatrixUserIDStr, ok := os.LookupEnv("MATRIX_USER_ID") if !ok { - slog.Error("MATRIX_USER_ID is not set") + logger.Error("MATRIX_USER_ID is not set") os.Exit(1) } MatrixUserID := id.UserID(MatrixUserIDStr) MatrixAccessKey, ok := os.LookupEnv("MATRIX_ACCESS_KEY") if !ok { - slog.Error("MATRIX_ACCESS_KEY is not set") + logger.Error("MATRIX_ACCESS_KEY is not set") os.Exit(1) } + MatrixPassword, ok := os.LookupEnv("MATRIX_PASSWORD") + if !ok { + logger.Error("MATRIX_PASSWORD is not set") + os.Exit(1) + } + BotDatabasePath, ok := os.LookupEnv("BOT_DATABASE_PATH") + if !ok { + logger.Error("BOT_DATABASE_PATH is not set") + os.Exit(1) + } + BotPickle, ok := os.LookupEnv("BOT_PICKLE") + if !ok { + logger.Error("BOT_PICKLE is not set") + } OpenaiAPIKey, ok := os.LookupEnv("OPENAI_API_KEY") if !ok { - slog.Error("OPENAI_API_KEY is not set") + logger.Error("OPENAI_API_KEY is not set") os.Exit(1) } // Create new OpenAI client openaiClient := openai.NewClient(OpenaiAPIKey) - //matrixClient, _ := mautrix.NewClient(MatrixHomeserver, MatrixUserID, MatrixAccessKey) - // - //syncer := matrixClient.Syncer.(*mautrix.DefaultSyncer) - //syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) { - // if evt.Content["membership"] == "invite" && *ev.StateKey == MatrixUserID { - // _, err := matrixClient.JoinRoom(ev.RoomID, "", nil) - // if err != nil { - // fmt.Println("Failed to join room:", err) - // } - // } - //}) - // - //syncer.OnEventType("m.room.message", func(ev *gomatrix.Event) { - // if ev.Sender != MatrixUserID { - // msgBody, _ := ev.Body() - // - // // Generate a message with OpenAI API - // openAiResp, err := openaiClient.CreateChatCompletion( - // context.Background(), - // openai.ChatCompletionRequest{ - // Model: openai.GPT4, - // Messages: []openai.ChatCompletionMessage{ - // { - // Role: openai.ChatMessageRoleSystem, - // Content: "You are a chatbot that helps people by responding to their questions with short messages.", - // }, - // - // { - // Role: openai.ChatMessageRoleUser, - // Content: msgBody, - // }, - // }, - // }) - // - // if err != nil { - // fmt.Println("OpenAI API returned with ", err) - // return - // } - // - // // Send the OpenAI response back to the chat - // responseText := openAiResp.Choices[len(openAiResp.Choices)-1].Message.Content - // formattedResponse := blackfriday.Run([]byte(responseText)) - // _, _ = matrixClient.SendFormattedText(ev.RoomID, responseText, string(formattedResponse)) - // } - //}) - // - //for { - // if err := matrixClient.Sync(); err != nil { - // fmt.Println("Sync() returned with ", err) - // } - //} - + // Create new Matrix client client, err := mautrix.NewClient(MatrixHomeserver, MatrixUserID, MatrixAccessKey) if err != nil { panic(err) @@ -104,28 +72,27 @@ func main() { var oei mautrix.OldEventIgnorer oei.Register(client.Syncer.(mautrix.ExtensibleSyncer)) + // logger for matrix client rl, err := readline.New("[no room]> ") if err != nil { panic(err) } defer rl.Close() - log := zerolog.New(zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { + matrixLogger := zerolog.New(zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { w.Out = rl.Stdout() w.TimeFormat = time.Stamp })).With().Timestamp().Logger() - //if !*debug { - // log = log.Level(zerolog.InfoLevel) - //} - client.Log = log + client.Log = matrixLogger var lastRoomID id.RoomID + // Set up sync events syncer := client.Syncer.(*mautrix.DefaultSyncer) syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) { lastRoomID = evt.RoomID rl.SetPrompt(fmt.Sprintf("%s> ", lastRoomID)) - log.Info(). + matrixLogger.Info(). Str("sender", evt.Sender.String()). Str("type", evt.Type.String()). Str("id", evt.ID.String()). @@ -184,31 +151,31 @@ func main() { } }) - //cryptoHelper, err := cryptohelper.NewCryptoHelper(client, []byte("meow"), "mautrix-example.db") - //if err != nil { - // panic(err) - //} - // - //// You can also store the user/device IDs and access token and put them in the client beforehand instead of using LoginAs. - ////client.UserID = "..." - ////client.DeviceID = "..." - ////client.AccessToken = "..." - //// You don't need to set a device ID in LoginAs because the crypto helper will set it for you if necessary. - ////cryptoHelper.LoginAs = &mautrix.ReqLogin{ - //// Type: mautrix.AuthTypePassword, - //// Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: *username}, - //// Password: *password, - ////} - //// If you want to use multiple clients with the same DB, you should set a distinct database account ID for each one. - ////cryptoHelper.DBAccountID = "" - //err = cryptoHelper.Init() - //if err != nil { - // panic(err) - //} - //// Set the client crypto helper in order to automatically encrypt outgoing messages - //client.Crypto = cryptoHelper + cryptoHelper, err := cryptohelper.NewCryptoHelper(client, []byte(BotPickle), BotDatabasePath) + if err != nil { + panic(err) + } - log.Info().Msg("Now running") + // You can also store the user/device IDs and access token and put them in the client beforehand instead of using LoginAs. + //client.UserID = "..." + //client.DeviceID = "..." + //client.AccessToken = "..." + // You don't need to set a device ID in LoginAs because the crypto helper will set it for you if necessary. + cryptoHelper.LoginAs = &mautrix.ReqLogin{ + Type: mautrix.AuthTypePassword, + Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: MatrixUserID.String()}, + Password: MatrixPassword, + } + // If you want to use multiple clients with the same DB, you should set a distinct database account ID for each one. + //cryptoHelper.DBAccountID = "" + err = cryptoHelper.Init() + if err != nil { + panic(err) + } + // Set the client crypto helper in order to automatically encrypt outgoing messages + client.Crypto = cryptoHelper + + matrixLogger.Info().Msg("Now running") syncCtx, cancelSync := context.WithCancel(context.Background()) var syncStopWait sync.WaitGroup syncStopWait.Add(1) @@ -225,26 +192,10 @@ func main() { signal.Notify(done, os.Interrupt) <-done - //for { - // line, err := rl.Readline() - // if err != nil { // io.EOF - // break - // } - // if lastRoomID == "" { - // log.Error().Msg("Wait for an incoming message before sending messages") - // continue - // } - // resp, err := client.SendText(lastRoomID, line) - // if err != nil { - // log.Error().Err(err).Msg("Failed to send event") - // } else { - // log.Info().Str("event_id", resp.EventID.String()).Msg("Event sent") - // } - //} cancelSync() syncStopWait.Wait() - //err = cryptoHelper.Close() - //if err != nil { - // log.Error().Err(err).Msg("Error closing database") - //} + err = cryptoHelper.Close() + if err != nil { + log.Error().Err(err).Msg("Error closing database") + } }