Files
go-receipt-tracker/config/config.go
Alex Savin b6d88a0ae8
Some checks failed
Deploy Project / deploy (push) Failing after 4s
Testing / test (1.23.x, ubuntu-latest) (push) Successful in 52s
Some changes
2025-02-11 17:05:21 -05:00

173 lines
6.6 KiB
Go

package config
import (
"log/slog"
"os"
"github.com/spf13/viper"
)
var (
Message_welcome = `Welcome to Receipts Tracker Bot - Your Ultimate Receipt Tracking Solution!
We are thrilled to have you join our community. At Receipts Tracker, we are committed to making your financial management effortless and efficient. Our advanced receipt tracking system is designed to help you organize, store, and manage all your receipts in one secure place.
Why Choose Receipts Tracker?
Easy Organization: Seamlessly categorize and store your receipts for quick access.
Secure Storage: Enjoy peace of mind with our top-notch security measures.
Effortless Management: Track your expenses and stay on top of your finances with ease.
User-Friendly Interface: Navigate our intuitive platform with ease, even if you are not tech-savvy.
Getting Started
Sign Up: Create your free account in just a few clicks.
Upload Receipts: Start uploading your receipts using our easy-to-use tools.
Track and Manage: Monitor your expenses, generate reports, and stay organized effortlessly.
We are here to support you every step of the way. If you have any questions or need assistance, our dedicated customer support team is just a click away.
Welcome aboard! We look forward to helping you take control of your financial management.
Best regards,
The Receipts Tracker Team`
Request = `That is a receipt.
Please parse it and send back only these items:
- items (any item has a type, like (meat, eggs, sandwich, burger, alcohol, cigars, ammo, gasoline, cat food, dog food, candies and etc)). If quantity of the item is not present consider it as 1, but check it right nex to the item name/title, it could be on the nest line or present like (2@1.99). Check if the item is taxable (true/false)
- quantity (if it is gas put gallons number)
- prices (if it is a gas use prices per gallon)
- datetime (convert it to the US format)
- merchant (name, address and phone number, in the format 123-456-7890, if present)
- payment type (cash, credit card, wire transfer, paypal, venmo and etc)
- credit card type ["AMEX", "VISA", "MASTER", "DISCOVER" and etc], number (only last 4 digits) and nethod of credit card payment (example: swipe, chip, contactless and etc), if type unknown keep variables empty
- category of the purchase, like (grocery, gas, restaurant, dinner, cafe, coffee, alcohol, parking and etc)
- credit card fee, if it present, otherwise consider it 0.0 (float)
- tax (could be found as Sales Tax), otherwise consider it 0.0 (float)
- tips, if that field filled and present, otherwise consider it 0.0 (float)
- total (if you cannot find total calculate it)
- receipt type, could be one of the three options (itemized, transactional or combined). Itemized receipt contains only list of the purchased items and does not include transaction (payment) data. Transactional include only information about payment/transaction and missing itemized information. Combined if it has items description and transaction data
in json format, please use this as an example
json
{
\"paid_at\": "10/14/2024 14:56:17",
\"type\": \"combined\",
\"merchant\": {
\"title\": \"Costco Wholesale\",
\"address\": \"123 John str, Manhattan, NY 10010\",
\"phone\": \"123-456-7890\"
}
\"payment_type\": \"credit card\",
\"credit_card\": {
\"type\": \"VISA\",
\"digits\": \"1234\",
\"method\": \"swipe\",
},
\"category\": \"gas\",
\"tax\": 0.0,
\"total\": 38.32,
\"cc_fee\": 0.0,
\"tips\": 0.0,
\"items\": [
{
\"item\": \"Regular Gas\",
\"quantity\": 13.740,
\"price\": 2.789,
\"category\": \"gasoline\"
\"taxable\": \"false\",
}
]
}
If you see column \"You pay\", please use that price.
Do not add any other text to the response.
Do not wrap output in markdown, only pure json`
// ApiGenimi = "AIzaSyBdyf4684EPy__xxLH5NDf8GImS1hGEQxE"
// ApiOpenAi = "sk-svcacct-o2Ued-dZUXs6gKJ2Lk0YkEAUeZiBPp-PVOieoWYuMBhVoTDDl8jAMAvRjXMT5BT-8ZR9XTP8YEoLT3BlbkFJri_8f6i9iJMJmzSH3owy4nSQ4DUbq0drCTvdrqb7MnVsc_vJY7xuR5i-JWJt1Owm5pqQ0p4YR0wA"
// ApiTelegram = "7307273503:AAGpj5eEd8eC9Ophi8rCDvtmfG46GRf2XEs"
)
// Config .
type Config struct {
Telegram *Telegram `json:"telegram" yaml:"telegram"`
Parsers map[string]*Parser `json:"parsers" yaml:"parsers"`
DataBase *DataBase `json:"database" yaml:"database"`
Listeners map[string]*Listener `json:"listeners" yaml:"listeners"`
Bus *Bus `json:"bus" yaml:"bus"`
StoragePath string `json:"storage_path" yaml:"storage_path"`
Timezone string `json:"timezone" yaml:"timezone"`
Logging *Logging `json:"logging" yaml:"logging"`
}
// Parser .
type Parser struct {
Type string `json:"type" yaml:"type"`
ApiKey string `json:"apikey" yaml:"apikey"`
Model string `json:"model,omitempty" yaml:"model,omitempty"`
}
// Telegram .
type Telegram struct {
ApiKey string `json:"apikey" yaml:"apikey"`
StoragePath string `json:"storagepath" yaml:"storagepath"`
}
// DB .
type DataBase struct {
DSN string `json:"dsn" yaml:"dsn"`
}
// Bus .
type Bus struct {
SubscriptionSize map[string]int `json:"subscriptionsize" yaml:"subscriptionsize"`
}
// Listeners .
type Listener struct {
ID string
Port int `json:"port" yaml:"port"`
Cert string `json:"cert,omitempty" yaml:"cert,omitempty"`
PKey string `json:"pkey,omitempty" yaml:"pkey,omitempty"`
}
// Logging .
type Logging struct {
Level string `json:"level" yaml:"level"`
Output string `json:"output" yaml:"output"`
Source bool `json:"source,omitempty" yaml:"source,omitempty"`
}
// New .
func New() (*Config, error) {
viper.SetConfigName("config") // name of config file (without extension)
viper.SetConfigType("yml") // REQUIRED if the config file does not have the extension in the name
viper.AddConfigPath("./") // optionally look for config in the working directory
viper.AddConfigPath("/app/config") // optionally look for config in the working directory
viper.AddConfigPath("/etc/tracker") // optionally look for config in the working directory
viper.AutomaticEnv()
viper.SetDefault("Timezone", "America/New_York")
viper.SetDefault("Logging.Level", "DEBUG")
viper.SetDefault("Logging.Output", "TEXT")
viper.SetDefault("Logging.Source", "false")
err := viper.ReadInConfig() // Find and read the config file
if err != nil {
slog.Error("cannot open config file", "error", err.Error())
os.Exit(1)
}
// viper.WatchConfig()
// viper.OnConfigChange(func(e fsnotify.Event) {
// log.Println("Config file changed:", e.Name)
// })
var config Config
if err := viper.Unmarshal(&config); err != nil {
slog.Error("cannot unmarshal config file", "error", err.Error())
os.Exit(1)
}
return &config, err
}