Replace env vars with toml config
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -48,10 +48,8 @@ Thumbs.db
|
||||
# Log files
|
||||
*.log
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
# Config files
|
||||
config.toml
|
||||
|
||||
# Sample and test audio files
|
||||
*.m4a
|
||||
|
@@ -1,25 +1,40 @@
|
||||
# Server configuration
|
||||
[server]
|
||||
port = 8080
|
||||
|
||||
# Database configuration
|
||||
[database]
|
||||
path = "data/transcriber.db"
|
||||
|
||||
# AWS S3 Configuration
|
||||
[aws]
|
||||
# Регион AWS (например: us-east-1, eu-west-1)
|
||||
AWS_REGION=us-east-1
|
||||
region = "us-east-1"
|
||||
|
||||
# AWS Access Key ID (получить в AWS Console)
|
||||
AWS_ACCESS_KEY_ID=your_access_key_id
|
||||
access_key_id = "your_access_key_id"
|
||||
|
||||
# AWS Secret Access Key (получить в AWS Console)
|
||||
AWS_SECRET_ACCESS_KEY=your_secret_access_key
|
||||
secret_access_key = "your_secret_access_key"
|
||||
|
||||
# Имя S3 bucket для загрузки файлов
|
||||
S3_BUCKET_NAME=your_bucket_name
|
||||
bucket_name = "your_bucket_name"
|
||||
|
||||
# Кастомный endpoint для S3 (оставить пустым для AWS S3, заполнить для MinIO или других S3-совместимых сервисов)
|
||||
S3_ENDPOINT=
|
||||
endpoint = ""
|
||||
|
||||
# Yandex Cloud Speech-to-Text Configuration
|
||||
[yandex]
|
||||
# API ключ для доступа к Yandex Cloud (получить в консоли Yandex Cloud)
|
||||
YANDEX_CLOUD_API_KEY=your_api_key_here
|
||||
api_key = "your_api_key_here"
|
||||
|
||||
# ID папки в Yandex Cloud (получить в консоли Yandex Cloud)
|
||||
YANDEX_CLOUD_FOLDER_ID=your_folder_id_here
|
||||
folder_id = "your_folder_id_here"
|
||||
|
||||
# Telegram Bot Configuration
|
||||
[telegram]
|
||||
# Токен Telegram бота (получить у @BotFather в Telegram)
|
||||
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
|
||||
bot_token = "your_telegram_bot_token_here"
|
||||
|
||||
# Таймаут обновлений Telegram бота (в секундах)
|
||||
update_timeout = 10
|
1
go.mod
1
go.mod
@@ -23,6 +23,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.2 // indirect
|
||||
|
2
go.sum
2
go.sum
@@ -1,3 +1,5 @@
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/aws/aws-sdk-go-v2 v1.37.2 h1:xkW1iMYawzcmYFYEV0UCMxc8gSsjCGEhBXQkdQywVbo=
|
||||
|
90
internal/config/config.go
Normal file
90
internal/config/config.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `toml:"server"`
|
||||
Database DatabaseConfig `toml:"database"`
|
||||
AWS AWSConfig `toml:"aws"`
|
||||
Yandex YandexConfig `toml:"yandex"`
|
||||
Telegram TelegramConfig `toml:"telegram"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port int `toml:"port"`
|
||||
ShutdownTimeout int `toml:"shutdown_timeout"`
|
||||
ForceShutdownTimeout int `toml:"force_shutdown_timeout"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Path string `toml:"path"`
|
||||
}
|
||||
|
||||
type AWSConfig struct {
|
||||
Region string `toml:"region"`
|
||||
AccessKey string `toml:"access_key_id"`
|
||||
SecretKey string `toml:"secret_access_key"`
|
||||
BucketName string `toml:"bucket_name"`
|
||||
Endpoint string `toml:"endpoint"`
|
||||
}
|
||||
|
||||
type YandexConfig struct {
|
||||
APIKey string `toml:"api_key"`
|
||||
FolderID string `toml:"folder_id"`
|
||||
}
|
||||
|
||||
type TelegramConfig struct {
|
||||
BotToken string `toml:"bot_token"`
|
||||
UpdateTimeout int `toml:"update_timeout"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns a Config with default values
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Server: ServerConfig{
|
||||
Port: 8080,
|
||||
ShutdownTimeout: 5,
|
||||
ForceShutdownTimeout: 20,
|
||||
},
|
||||
Database: DatabaseConfig{
|
||||
Path: "data/transcriber.db",
|
||||
},
|
||||
AWS: AWSConfig{
|
||||
Region: "ru-central1",
|
||||
AccessKey: "",
|
||||
SecretKey: "",
|
||||
BucketName: "",
|
||||
Endpoint: "",
|
||||
},
|
||||
Yandex: YandexConfig{
|
||||
APIKey: "",
|
||||
FolderID: "",
|
||||
},
|
||||
Telegram: TelegramConfig{
|
||||
BotToken: "",
|
||||
UpdateTimeout: 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// LoadConfig loads configuration from a TOML file
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
// Check if file exists
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("config file not found: %s", path)
|
||||
}
|
||||
|
||||
config := DefaultConfig()
|
||||
|
||||
// Load configuration from file
|
||||
if _, err := toml.DecodeFile(path, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode config file: %w", err)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
50
main.go
50
main.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
ffmpegmv "git.vakhrushev.me/av/transcriber/internal/adapter/metaviewer/ffmpeg"
|
||||
"git.vakhrushev.me/av/transcriber/internal/adapter/recognizer/yandex"
|
||||
"git.vakhrushev.me/av/transcriber/internal/adapter/repo/sqlite"
|
||||
"git.vakhrushev.me/av/transcriber/internal/config"
|
||||
httpcontroller "git.vakhrushev.me/av/transcriber/internal/controller/http"
|
||||
tgcontroller "git.vakhrushev.me/av/transcriber/internal/controller/tg"
|
||||
"git.vakhrushev.me/av/transcriber/internal/controller/worker"
|
||||
@@ -31,10 +33,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TelegramUpdateTimeout = 10
|
||||
ServerShutdownTimeout = 5
|
||||
|
||||
ForceShutdownTimeout = 20
|
||||
ForceShutdownTimeout = 20
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -44,6 +44,22 @@ func main() {
|
||||
}))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
// Parse command line flags
|
||||
configPath := flag.String("c", "config.toml", "Path to config file")
|
||||
flag.StringVar(configPath, "config", "config.toml", "Path to config file (alias for -c)")
|
||||
flag.Parse()
|
||||
|
||||
// Load configuration
|
||||
cfg, err := config.LoadConfig(*configPath)
|
||||
if err != nil {
|
||||
// If config file doesn't exist, use defaults
|
||||
cfg = config.DefaultConfig()
|
||||
// Log that we're using default config
|
||||
logger.Info("Using default configuration", "config_path", *configPath, "error", err)
|
||||
} else {
|
||||
logger.Info("Configuration loaded successfully", "config_path", *configPath)
|
||||
}
|
||||
|
||||
// Загружаем переменные окружения из .env файла
|
||||
if err := godotenv.Load(); err != nil {
|
||||
logger.Warn("Warning: .env file not found, using system environment variables")
|
||||
@@ -55,7 +71,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
db, err := sql.Open("sqlite3", "data/transcriber.db")
|
||||
db, err := sql.Open("sqlite3", cfg.Database.Path)
|
||||
if err != nil {
|
||||
logger.Error("failed to open database", "error", err)
|
||||
os.Exit(1)
|
||||
@@ -84,13 +100,13 @@ func main() {
|
||||
converter := ffmpegconv.NewFfmpegConverter()
|
||||
|
||||
recognizer, err := yandex.NewYandexAudioRecognizerService(yandex.YandexAudioRecognizerConfig{
|
||||
Region: os.Getenv("AWS_REGION"),
|
||||
AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
|
||||
SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
|
||||
BucketName: os.Getenv("S3_BUCKET_NAME"),
|
||||
Endpoint: os.Getenv("S3_ENDPOINT"),
|
||||
ApiKey: os.Getenv("YANDEX_CLOUD_API_KEY"),
|
||||
FolderID: os.Getenv("YANDEX_CLOUD_FOLDER_ID"),
|
||||
Region: cfg.AWS.Region,
|
||||
AccessKey: cfg.AWS.AccessKey,
|
||||
SecretKey: cfg.AWS.SecretKey,
|
||||
BucketName: cfg.AWS.BucketName,
|
||||
Endpoint: cfg.AWS.Endpoint,
|
||||
ApiKey: cfg.Yandex.APIKey,
|
||||
FolderID: cfg.Yandex.FolderID,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("failed to create audio recognizer", "error", err)
|
||||
@@ -109,8 +125,8 @@ func main() {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
tgConfig := tgcontroller.TelegramConfig{
|
||||
BotToken: os.Getenv("TELEGRAM_BOT_TOKEN"),
|
||||
UpdateTimeout: TelegramUpdateTimeout,
|
||||
BotToken: cfg.Telegram.BotToken,
|
||||
UpdateTimeout: cfg.Telegram.UpdateTimeout,
|
||||
}
|
||||
|
||||
// Создаем Telegram бот
|
||||
@@ -182,7 +198,7 @@ func main() {
|
||||
|
||||
// Создаем HTTP сервер
|
||||
srv := &http.Server{
|
||||
Addr: ":8080",
|
||||
Addr: fmt.Sprintf(":%d", cfg.Server.Port),
|
||||
Handler: router,
|
||||
}
|
||||
|
||||
@@ -190,7 +206,7 @@ func main() {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
logger.Info("Starting HTTP server", "port", 8080)
|
||||
logger.Info("Starting HTTP server", "port", cfg.Server.Port)
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Error("HTTP server error", "error", err)
|
||||
}
|
||||
@@ -214,7 +230,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Создаем контекст с таймаутом для graceful shutdown HTTP сервера
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), ServerShutdownTimeout*time.Second)
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), time.Duration(cfg.Server.ShutdownTimeout)*time.Second)
|
||||
defer shutdownCancel()
|
||||
|
||||
// Останавливаем HTTP сервер
|
||||
@@ -239,7 +255,7 @@ func main() {
|
||||
select {
|
||||
case <-done:
|
||||
logger.Info("All workers stopped gracefully")
|
||||
case <-time.After(ForceShutdownTimeout * time.Second):
|
||||
case <-time.After(time.Duration(cfg.Server.ForceShutdownTimeout) * time.Second):
|
||||
logger.Warn("Timeout reached, forcing shutdown")
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user