You've already forked monobank-firefly3-bot
							
							Compare commits
	
		
			2 Commits
		
	
	
		
			1646d484fb
			...
			fb7796c475
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						fb7796c475
	
				 | 
					
					
						|||
| 
						
						
							
						
						e1c9f56921
	
				 | 
					
					
						
@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +29,15 @@ 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)
 | 
			
		||||
 | 
			
		||||
@@ -92,8 +102,21 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
 | 
			
		||||
			}
 | 
			
		||||
			break
 | 
			
		||||
		} else {
 | 
			
		||||
			// check name match
 | 
			
		||||
			isDescriptionMatch := false
 | 
			
		||||
			if row.NamesLooseMatch {
 | 
			
		||||
				for _, name := range row.Names {
 | 
			
		||||
					if strings.HasPrefix(monobankTransaction.Data.StatementItem.Description, name) {
 | 
			
		||||
						isDescriptionMatch = true
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				isDescriptionMatch = slices.Contains(row.Names, monobankTransaction.Data.StatementItem.Description)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// check name & mcc
 | 
			
		||||
			if !(slices.Contains(row.Names, monobankTransaction.Data.StatementItem.Description) || slices.Contains(row.MccCodes, int(monobankTransaction.Data.StatementItem.Mcc))) {
 | 
			
		||||
			if !(isDescriptionMatch || slices.Contains(row.MccCodes, int(monobankTransaction.Data.StatementItem.Mcc))) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -135,7 +158,7 @@ func ImportTransaction(monobankTransaction monobank.WebHookResponse) error {
 | 
			
		||||
 | 
			
		||||
				// when transfer between different currencies, convert
 | 
			
		||||
				sourceAccount := App().Config.GetAccountByFirefly3Name(firefly3Transaction.SourceName)
 | 
			
		||||
				if sourceAccount.Currency != destAccount.Currency {
 | 
			
		||||
				if len(sourceAccount.Currency) > 0 && sourceAccount.Currency != destAccount.Currency {
 | 
			
		||||
					// swap amounts
 | 
			
		||||
					firefly3Transaction.ForeignAmount = firefly3Transaction.Amount
 | 
			
		||||
					firefly3Transaction.Amount = strconv.Itoa(int(math.Abs(math.Round(monobankTransaction.Data.StatementItem.OperationAmount / 100))))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
@@ -20,3 +22,49 @@ func LogString(str string) {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LogContainsTransactionID(transactionID string) (bool, error) {
 | 
			
		||||
	if len(os.Getenv("LOG_FILE")) == 0 {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// open the log file for reading.
 | 
			
		||||
	logFile, err := os.Open(os.Getenv("LOG_FILE"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, fmt.Errorf("error opening log file: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer logFile.Close()
 | 
			
		||||
 | 
			
		||||
	// create a new scanner to read the log file line by line.
 | 
			
		||||
	scanner := bufio.NewScanner(logFile)
 | 
			
		||||
 | 
			
		||||
	// iterate over each line of the log file.
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		// unmarshal the JSON data from the current line.
 | 
			
		||||
		var transactionData struct {
 | 
			
		||||
			Data struct {
 | 
			
		||||
				StatementItem struct {
 | 
			
		||||
					ID string `json:"id"`
 | 
			
		||||
				} `json:"statementItem"`
 | 
			
		||||
			} `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		err := json.Unmarshal(scanner.Bytes(), &transactionData)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// skip lines that are not valid JSON.
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// check if the transaction ID matches the given ID.
 | 
			
		||||
		if transactionData.Data.StatementItem.ID == transactionID {
 | 
			
		||||
			return true, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check for any errors that occurred during scanning.
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		return false, fmt.Errorf("error scanning log file: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// transaction ID not found in the log file.
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +1,26 @@
 | 
			
		||||
package config
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	Accounts         []ConfigAccount          `json:"accounts"`
 | 
			
		||||
	TransactionTypes []ConfigTransactionTypes `json:"transaction_types"`
 | 
			
		||||
	Accounts         []Account          `json:"accounts"`
 | 
			
		||||
	TransactionTypes []TransactionTypes `json:"transaction_types"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ConfigAccount struct {
 | 
			
		||||
type Account struct {
 | 
			
		||||
	Firefly3Name string `json:"firefly3_name,omitempty"`
 | 
			
		||||
	MonobankId   string `json:"monobank_id,omitempty"`
 | 
			
		||||
	Currency     string `json:"currency,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ConfigTransactionTypes struct {
 | 
			
		||||
	Names       []string                      `json:"names,omitempty"`
 | 
			
		||||
	NamesRefund []string                      `json:"names_refund,omitempty"`
 | 
			
		||||
	MccCodes    []int                         `json:"mcc_codes,omitempty"`
 | 
			
		||||
	Firefly3    ConfigTransactionTypeFirefly3 `json:"firefly3,omitempty"`
 | 
			
		||||
	SumMax      int                           `json:"sum_max,omitempty"`
 | 
			
		||||
type TransactionTypes struct {
 | 
			
		||||
	Names           []string                `json:"names,omitempty"`
 | 
			
		||||
	NamesRefund     []string                `json:"names_refund,omitempty"`
 | 
			
		||||
	NamesLooseMatch bool                    `json:"names_loose_match,omitempty"` // "name%" match
 | 
			
		||||
	MccCodes        []int                   `json:"mcc_codes,omitempty"`
 | 
			
		||||
	Firefly3        TransactionTypeFirefly3 `json:"firefly3,omitempty"`
 | 
			
		||||
	SumMax          int                     `json:"sum_max,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ConfigTransactionTypeFirefly3 struct {
 | 
			
		||||
type TransactionTypeFirefly3 struct {
 | 
			
		||||
	Type                     string `json:"type,omitempty"`
 | 
			
		||||
	Destination              string `json:"destination,omitempty"`
 | 
			
		||||
	Description              string `json:"description,omitempty"`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,21 @@
 | 
			
		||||
package config
 | 
			
		||||
 | 
			
		||||
func (c *Config) GetAccountByMonobankId(q string) ConfigAccount {
 | 
			
		||||
func (c *Config) GetAccountByMonobankId(q string) Account {
 | 
			
		||||
	for _, row := range c.Accounts {
 | 
			
		||||
		if row.MonobankId == q {
 | 
			
		||||
			return row
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ConfigAccount{}
 | 
			
		||||
	return Account{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) GetAccountByFirefly3Name(q string) ConfigAccount {
 | 
			
		||||
func (c *Config) GetAccountByFirefly3Name(q string) Account {
 | 
			
		||||
	for _, row := range c.Accounts {
 | 
			
		||||
		if row.Firefly3Name == q {
 | 
			
		||||
			return row
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ConfigAccount{}
 | 
			
		||||
	return Account{}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user