diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index 8a6f182..9494df2 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -12,19 +12,27 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Log in to Gitea registry + if: ${{ secrets.GITEA_REGISTRY_USERNAME != '' && secrets.GITEA_REGISTRY_PASSWORD != '' }} + uses: docker/login-action@v3 + with: + registry: git.kogami.xyz + username: ${{ secrets.GITEA_REGISTRY_USERNAME }} + password: ${{ secrets.GITEA_REGISTRY_PASSWORD }} + - name: Build image uses: docker/build-push-action@v6 with: context: . + platforms: linux/arm64 push: false load: true tags: matrix-bot:latest + cache-from: type=registry,ref=git.kogami.xyz/foglar/matrix-bot:buildcache + cache-to: type=registry,ref=git.kogami.xyz/foglar/matrix-bot:buildcache,mode=max - name: Run container env: @@ -37,6 +45,7 @@ jobs: MATRIX_USERNAME: ${{ secrets.MATRIX_USERNAME }} MATRIX_PASSWORD: ${{ secrets.MATRIX_PASSWORD }} MATRIX_ROOM_ID: ${{ secrets.MATRIX_ROOM_ID }} + MATRIX_CRYPTO_RESET_ON_MISMATCH: "true" run: | docker run --rm \ -e MATRIX_HOMESERVER \ @@ -48,6 +57,7 @@ jobs: -e MATRIX_USERNAME \ -e MATRIX_PASSWORD \ -e MATRIX_ROOM_ID \ + -e MATRIX_CRYPTO_RESET_ON_MISMATCH \ -e MATRIX_WORDLIST=/data/sowpods.csv \ -e MATRIX_CRYPTO_DB=/data/crypto.db \ -v matrix-bot-data:/data \ diff --git a/Dockerfile b/Dockerfile index 18641c8..3844c9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,10 +6,10 @@ WORKDIR /app RUN apk add --no-cache ca-certificates olm-dev build-base COPY go.mod ./ -RUN go mod download +RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY . . -RUN CGO_ENABLED=1 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-arm64} go build -o matrix-bot ./ +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=1 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-arm64} go build -o matrix-bot ./ FROM alpine:3.19 WORKDIR /app diff --git a/main.go b/main.go index f9faa9a..5d5ed7b 100644 --- a/main.go +++ b/main.go @@ -3,10 +3,12 @@ package main import ( "context" "encoding/json" + "errors" "log" "matrix-bot/bot" "os" "path/filepath" + "strings" "sync" "maunium.net/go/mautrix" @@ -27,6 +29,7 @@ var pickleKeyString string var recoveryKey string var cryptoDBPath string var credentialsPath string +var cryptoResetOnMismatch bool type storedCredentials struct { UserID string `json:"user_id"` @@ -147,6 +150,30 @@ func loadConfig() { recoveryKey = envOrFatal("MATRIX_RECOVERY_KEY") cryptoDBPath = envOrDefault("MATRIX_CRYPTO_DB", "crypto.db") credentialsPath = envOrDefault("MATRIX_CREDENTIALS_PATH", "/data/credentials.json") + cryptoResetOnMismatch = strings.EqualFold(envOrDefault("MATRIX_CRYPTO_RESET_ON_MISMATCH", ""), "true") || + envOrDefault("MATRIX_CRYPTO_RESET_ON_MISMATCH", "") == "1" +} + +func isOlmAccountMismatch(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "olm account is not marked as shared") +} + +func resetCryptoState() error { + var resetErr error + if cryptoDBPath != "" { + if err := os.Remove(cryptoDBPath); err != nil && !errors.Is(err, os.ErrNotExist) { + resetErr = err + } + } + if credentialsPath != "" { + if err := os.Remove(credentialsPath); err != nil && !errors.Is(err, os.ErrNotExist) { + resetErr = err + } + } + return resetErr } func main() { @@ -219,6 +246,16 @@ func main() { cryptoHelper, err := setupCryptoHelper(client) if err != nil { + if isOlmAccountMismatch(err) { + log.Println("Detected olm account mismatch with server keys") + if cryptoResetOnMismatch { + if resetErr := resetCryptoState(); resetErr != nil { + log.Fatal(resetErr) + } + log.Fatal("Reset crypto state due to mismatch. Restart the container to re-login.") + } + log.Fatal("Crypto mismatch. Remove crypto DB and credentials, then restart.") + } log.Fatal(err) } client.Crypto = cryptoHelper @@ -274,6 +311,16 @@ func main() { log.Println("Sync complete") if err := verifyWithRecoveryKey(cryptoHelper.Machine()); err != nil { + if isOlmAccountMismatch(err) { + log.Println("Detected olm account mismatch with server keys") + if cryptoResetOnMismatch { + if resetErr := resetCryptoState(); resetErr != nil { + log.Fatal(resetErr) + } + log.Fatal("Reset crypto state due to mismatch. Restart the container to re-login.") + } + log.Fatal("Crypto mismatch. Remove crypto DB and credentials, then restart.") + } log.Fatal(err) }