Compare commits

...

26 Commits

Author SHA1 Message Date
a5c9403576 Add transaction adjustment on cancellation (when amount differs)
All checks were successful
build docker image / docker-build (push) Successful in 2m16s
2025-06-06 16:54:36 +03:00
ebb213a3cc Add transaction adjustment on cancellation (when amount differs)
Some checks failed
build docker image / docker-build (push) Has been cancelled
2025-06-06 16:54:16 +03:00
f947606131 Update .gitea/workflows/build-docker-image.yaml
All checks were successful
build docker image / docker-build (push) Successful in 1m4s
2025-01-04 21:47:29 +02:00
464093e5bd Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 53s
2024-11-15 13:29:14 +02:00
f96f88d16e Add docker deploy
Some checks failed
build docker image / docker-build (push) Has been cancelled
2024-11-15 13:28:44 +02:00
686c46bf78 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 1m32s
2024-11-04 21:58:44 +02:00
38b4e89a02 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 1m32s
2024-11-04 20:39:15 +02:00
3986e1c9de Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 49s
2024-11-04 20:18:28 +02:00
f0e26a0cd2 Add docker deploy
Some checks failed
build docker image / docker-build (push) Has been cancelled
2024-11-04 20:18:18 +02:00
00657a8660 Add docker deploy
Some checks failed
build docker image / docker-build (push) Has been cancelled
2024-11-04 20:18:07 +02:00
39459202f1 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 1m14s
2024-11-04 20:14:17 +02:00
896e91e61e Add docker deploy 2024-11-04 20:14:10 +02:00
950d6649b2 Add docker deploy
Some checks failed
build docker image / docker-build (push) Has been cancelled
2024-11-04 20:14:03 +02:00
a3e2a462a3 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 46s
2024-11-04 20:12:59 +02:00
34dce58d91 Add docker deploy
Some checks failed
build docker image / docker-build (push) Failing after 47s
2024-11-04 20:11:50 +02:00
de69376bff Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 48s
2024-11-04 20:10:27 +02:00
e0d4758540 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 48s
2024-11-04 20:07:38 +02:00
efb5bf0b3b Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 47s
2024-11-04 20:05:44 +02:00
daf5f8fb03 Add docker deploy
All checks were successful
build docker image / docker-build (push) Successful in 47s
2024-11-04 19:54:06 +02:00
b05b1b9b48 Remove load .env from bin path
Some checks failed
build docker image / docker-build (push) Failing after 51s
2024-11-04 19:44:42 +02:00
074c32a8f1 Remove load .env from bin path 2024-10-08 16:58:38 +03:00
917d6d9103 Remove load .env from bin path 2024-10-08 16:58:13 +03:00
540eef981f Loan .env from bin path 2024-10-08 16:04:54 +03:00
7c03492676 Update dependencies 2024-09-25 19:57:44 +03:00
cd31de87e5 Fix webhook transactions never been logging 2024-09-07 11:38:02 +03:00
25212fbd1c Fix webhook transactions never been logging 2024-08-29 16:03:08 +03:00
7 changed files with 125 additions and 31 deletions

View File

@ -0,0 +1,34 @@
name: build docker image
on:
- push
jobs:
docker-build:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: gitea.stuzer.link
username: ${{ gitea.repository_owner }}
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64
push: true
tags: gitea.stuzer.link/stuzer05/monobank-firefly3-bot:latest
cache-from: type=registry,ref=gitea.stuzer.link/stuzer05/monobank-firefly3-bot:latest
cache-to: type=inline

22
Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM golang:1.23.2 AS builder
# Install certificates
RUN apt-get update && apt-get install -y ca-certificates
WORKDIR /app
COPY go.mod go.sum .
RUN go mod download && go mod verify
# Copy project files
COPY . .
# Build
RUN make
FROM scratch
COPY --from=builder /app/monobank-firefly3-bot /app
ENTRYPOINT ["/app"]

View File

@ -29,15 +29,6 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
return err
}
// check if transaction hs been logged
isTransactionAlreadyLogged, err := LogContainsTransactionID(monobankTransaction.Data.StatementItem.Id)
if err != nil {
return err
}
if isTransactionAlreadyLogged {
return nil
}
// find accounts
destAccount := App().Config.GetAccountByMonobankId(monobankTransaction.Data.Account)
@ -64,7 +55,7 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
return err
}
// find matching transaction to delete
// find matching transaction to adjust/delete
isDeleted := false
for _, tRows := range oldTransactions.Data {
if isDeleted {
@ -79,24 +70,54 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
}
// read monobank transaction
var monobankTransaction monobank.WebHookResponse
err = json.Unmarshal(notesBytes, &monobankTransaction)
var monobankTransactionOld monobank.WebHookResponse
err = json.Unmarshal(notesBytes, &monobankTransactionOld)
if err != nil {
continue
}
// Parse amounts
sumNew := int64(math.Abs(math.Round(monobankTransaction.Data.StatementItem.Amount/100))) - int64(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate/100)))
sumOldFloat, _ := strconv.ParseFloat(tRow.Amount, 64)
sumOld := int64(sumOldFloat)
// find transaction
sum := int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.Amount/100))) - int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.CommissionRate/100)))
sum2, _ := strconv.ParseFloat(tRow.Amount, 64)
if slices.Contains(row.Names, monobankTransaction.Data.StatementItem.Description) && sum == int(sum2) {
if slices.Contains(row.Names, monobankTransactionOld.Data.StatementItem.Description) {
if sumNew == sumOld {
// delete transaction
opts := firefly3.TransactionsApiDeleteTransactionOpts{}
_, err := App().Firefly3Client.TransactionsApi.DeleteTransaction(context.Background(), tRows.Id, &opts)
if err != nil {
return err
}
} else {
// adjust transaction
opts := firefly3.TransactionsApiUpdateTransactionOpts{}
body := firefly3.TransactionUpdate{
Transactions: []firefly3.TransactionSplitUpdate{
{
Description: tRow.Description,
CategoryId: tRow.CategoryId,
DestinationId: tRow.DestinationId,
SourceId: tRow.SourceId,
CurrencyId: tRow.CurrencyId,
ExternalUrl: tRow.ExternalUrl,
Date: tRow.Date,
DueDate: tRow.DueDate,
Tags: tRow.Tags,
Notes: tRow.Notes,
// Notes: string(monobankTransactionJson),
Amount: strconv.FormatInt(sumOld-sumNew, 10),
},
},
}
_, _, err := App().Firefly3Client.TransactionsApi.UpdateTransaction(context.Background(), body, tRows.Id, &opts)
if err != nil {
return err
}
}
isDeleted = true
isDeleted = true // break 2
}
}
}

4
go.mod
View File

@ -4,12 +4,12 @@ go 1.23
require (
gitea.stuzer.link/stuzer05/go-firefly3/v2 v2.1.0
gitea.stuzer.link/stuzer05/go-monobank v0.2303.0
gitea.stuzer.link/stuzer05/go-monobank v0.2303.1
github.com/antihax/optional v1.0.0
github.com/joho/godotenv v1.5.1
)
require (
github.com/sanity-io/litter v1.5.5 // indirect
golang.org/x/oauth2 v0.22.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
)

4
go.sum
View File

@ -2,6 +2,8 @@ gitea.stuzer.link/stuzer05/go-firefly3/v2 v2.1.0 h1:t+FOFg48PPN2n6SO6PwbqVpHGqYK
gitea.stuzer.link/stuzer05/go-firefly3/v2 v2.1.0/go.mod h1:FNdERhJjtqfkBQqR2EvB7T3h6eGJVid4xcBCUu1/9FU=
gitea.stuzer.link/stuzer05/go-monobank v0.2303.0 h1:BDv3h9bk5Fs3iI51W+pXmjPBAQn9T+YZu+B/lmbeBqc=
gitea.stuzer.link/stuzer05/go-monobank v0.2303.0/go.mod h1:y/jOBU1U+NNR5umvDH+scrOWk0byZGZrMb4PHEehyrk=
gitea.stuzer.link/stuzer05/go-monobank v0.2303.1 h1:2IdaL70SVyb3aUqlC6TNNi9VOyliYDdiqKSzhCwHmaE=
gitea.stuzer.link/stuzer05/go-monobank v0.2303.1/go.mod h1:sZvm8Jhtwpup3/X0acYuT0b+v+r4X0SnCBrJxQjlqkw=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -19,3 +21,5 @@ golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=

11
main.go
View File

@ -17,10 +17,7 @@ import (
func main() {
// load .env
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("error loading .env file")
}
godotenv.Load(".env")
// init app
app.Init()
@ -63,13 +60,13 @@ func main() {
}
} else if len(*flagMonobankDoTransaction) > 0 {
var monobankTransaction monobank.WebHookResponse
err = json.Unmarshal([]byte(*flagMonobankDoTransaction), &monobankTransaction)
err := json.Unmarshal([]byte(*flagMonobankDoTransaction), &monobankTransaction)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err := app.ImportTransaction(monobankTransaction)
err = app.ImportTransaction(monobankTransaction)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
@ -81,7 +78,7 @@ func main() {
// register monobank webhook
_, err := app.App().MonobankClient.Api.PersonalWebhookPost(context.Background(), monobank.SetWebHook{WebHookUrl: webhookUrl}, os.Getenv("MONOBANK_TOKEN"))
if err != nil {
log.Fatalln("failed to register monobank webhook")
log.Fatalln("failed to register monobank webhook: " + err.Error())
}
// set webhook

View File

@ -9,6 +9,10 @@ import (
)
func handleWebhook(w http.ResponseWriter, r *http.Request) {
// Parse URL query parameters
queryParams := r.URL.Query()
isRetry := queryParams.Get("retry") == "true"
// read request body bytes
body, err := io.ReadAll(r.Body)
if err != nil {
@ -18,7 +22,7 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
}
// log body string
app.LogString(string(body))
defer app.LogString(string(body))
// check request empty body
if len(string(body)) == 0 {
@ -36,6 +40,18 @@ func handleWebhook(w http.ResponseWriter, r *http.Request) {
return
}
// only check for logged transaction if not a retry
if !isRetry {
isTransactionAlreadyLogged, err := app.LogContainsTransactionID(monobankTransaction.Data.StatementItem.Id)
if err != nil {
app.LogString(err.Error())
return
}
if isTransactionAlreadyLogged {
return
}
}
err = app.ImportTransaction(monobankTransaction)
if err != nil {
app.LogString(err.Error())