diff --git a/server/go.mod b/server/go.mod index 14dedfd..edbed2c 100644 --- a/server/go.mod +++ b/server/go.mod @@ -6,6 +6,7 @@ require ( github.com/fsnotify/fsnotify v1.8.0 github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/jackc/pgx/v5 v5.7.1 + github.com/studio-b12/gowebdav v0.10.0 ) require ( diff --git a/server/go.sum b/server/go.sum index 9112d07..537e146 100644 --- a/server/go.sum +++ b/server/go.sum @@ -20,8 +20,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/studio-b12/gowebdav v0.10.0 h1:Yewz8FFiadcGEu4hxS/AAJQlHelndqln1bns3hcJIYc= +github.com/studio-b12/gowebdav v0.10.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= diff --git a/server/internal/log_backup/log_backup.go b/server/internal/log_backup/log_backup.go new file mode 100644 index 0000000..67811c5 --- /dev/null +++ b/server/internal/log_backup/log_backup.go @@ -0,0 +1,60 @@ +package log_backup + +import ( + "fmt" + "log" + + "github.com/Vomitblood/cspj-application/server/internal/webdav" + "github.com/studio-b12/gowebdav" +) + +// TODO: use values from config file +var localLogPaths = []string{ + "/path/to/file1.log", + "/path/to/file2.log", +} + +var remoteFiles = []string{ + "/my/remote/folder/file1.log", + "/my/remote/folder/file2.log", +} + +func BackupLogs(client *gowebdav.Client) error { + // check if there are equal number of local and remote file paths + if len(localLogPaths) != len(remoteFiles) { + return fmt.Errorf("mismatch between local log paths and remote paths") + } + + // loop through each file and upload it + for i := range localLogPaths { + err := webdav.UploadFile(client, localLogPaths[i], remoteFiles[i]) + if err != nil { + log.Printf("Error uploading file %s: %v", localLogPaths[i], err) + return fmt.Errorf("error uploading file %s: %v", localLogPaths[i], err) + } else { + log.Printf("Successfully uploaded file: %s", localLogPaths[i]) + } + } + + return nil +} + +func RestoreLogs(client *gowebdav.Client) error { + // check if there are equal number of local and remote file paths + if len(remoteFiles) != len(localLogPaths) { + return fmt.Errorf("mismatch between remote files and local paths") + } + + // loop through each remote file and download it + for i := range remoteFiles { + err := webdav.DownloadFile(client, remoteFiles[i], localLogPaths[i]) + if err != nil { + log.Printf("Error downloading file %s: %v", remoteFiles[i], err) + return fmt.Errorf("error downloading file %s: %v", remoteFiles[i], err) + } else { + log.Printf("Successfully downloaded file: %s", remoteFiles[i]) + } + } + + return nil +} diff --git a/server/internal/log_watcher/log_watcher.go b/server/internal/log_watcher/log_watcher.go index 7d111ba..a4910da 100644 --- a/server/internal/log_watcher/log_watcher.go +++ b/server/internal/log_watcher/log_watcher.go @@ -24,7 +24,7 @@ type LogEntry struct { } `json:"audit_data"` } -func watchLogFile(bot *tg.BotAPI) { +func WatchFile(bot *tg.BotAPI) { watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal("Failed to initialize watcher:", err) diff --git a/server/internal/telegram/telegram.go b/server/internal/telegram/telegram.go index 7cb4283..4773651 100644 --- a/server/internal/telegram/telegram.go +++ b/server/internal/telegram/telegram.go @@ -4,7 +4,9 @@ import ( "fmt" "log" + "github.com/Vomitblood/cspj-application/server/internal/log_backup" tg "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "github.com/studio-b12/gowebdav" ) const ( @@ -18,7 +20,7 @@ type LogEntry struct { } `json:"audit_data"` } -func TelegramBotInit() (*tg.BotAPI, error) { +func Init(client *gowebdav.Client) *tg.BotAPI { bot, err := tg.NewBotAPI(telegramToken) if err != nil { log.Fatal("Failed to create Telegram bot:", err) @@ -33,7 +35,50 @@ func TelegramBotInit() (*tg.BotAPI, error) { log.Fatal("Failed to send test message:", err) } - return bot, nil + go handleUpdates(bot, client) + + return bot +} + +// function to handle commands from user on tg +func handleUpdates(bot *tg.BotAPI, webdavClient *gowebdav.Client) { + u := tg.NewUpdate(0) + u.Timeout = 60 + updates := bot.GetUpdatesChan(u) + + for update := range updates { + if update.Message != nil { + command := update.Message.Text + + // /backup_logs + if command == "/backup_logs" { + err := log_backup.BackupLogs(webdavClient) + if err != nil { + sendTelegramResponse(bot, fmt.Sprintf("Failed to backup logs: %v", err)) + } else { + sendTelegramResponse(bot, "Successfully backed up log files") + } + } + + // Check for /download_logs command to download files from WebDAV + if command == "/restore_logs" { + err := log_backup.RestoreLogs(webdavClient) + if err != nil { + sendTelegramResponse(bot, fmt.Sprintf("Failed to restore logs: %v", err)) + } else { + sendTelegramResponse(bot, "Successfully restored log files") + } + } + } + } +} + +func sendTelegramResponse(bot *tg.BotAPI, message string) { + msg := tg.NewMessage(telegramChatID, message) + _, err := bot.Send(msg) + if err != nil { + log.Println("Failed to send Telegram message:", err) + } } func SendTelegramAlert(bot *tg.BotAPI, message string) { diff --git a/server/internal/webdav/webdav.go b/server/internal/webdav/webdav.go new file mode 100644 index 0000000..900bc89 --- /dev/null +++ b/server/internal/webdav/webdav.go @@ -0,0 +1,73 @@ +package webdav + +import ( + "fmt" + "log" + "os" + + "github.com/studio-b12/gowebdav" +) + +type WebDAVClient struct { + Client *gowebdav.Client +} + +const ( + // TODO: use values from config file + webdavURL = "https://webdav.vomitblood.com" + webdavUser = "Vomitblood" + webdavPassword = "alpine" +) + +func Init() *gowebdav.Client { + // initialize the webdav client + client := gowebdav.NewClient(webdavURL, webdavUser, webdavPassword) + + // establish a connection to the webdav server + err := client.Connect() + if err != nil { + log.Fatalf("Failed to connect to WebDAV server: %v", err) + } + + log.Println("Connected to WebDAV server") + return client +} + +func CreateDirectory(client *gowebdav.Client, remoteDir string) error { + err := client.Mkdir(remoteDir, 0755) + if err != nil { + return fmt.Errorf("failed to create directory %s: %v", remoteDir, err) + } + log.Printf("Created directory: %s", remoteDir) + return nil +} + +func UploadFile(client *gowebdav.Client, localFilePath string, remoteFilePath string) error { + bytes, err := os.ReadFile(localFilePath) + if err != nil { + return fmt.Errorf("failed to read file %s: %v", localFilePath, err) + } + + err = client.Write(remoteFilePath, bytes, 0644) + if err != nil { + return fmt.Errorf("failed to upload file %s: %v", localFilePath, err) + } + + log.Printf("Uploaded file: %s to %s", localFilePath, remoteFilePath) + return nil +} + +func DownloadFile(client *gowebdav.Client, remoteFilePath string, localFilePath string) error { + bytes, err := client.Read(remoteFilePath) + if err != nil { + return fmt.Errorf("failed to download file %s: %v", remoteFilePath, err) + } + + err = os.WriteFile(localFilePath, bytes, 0644) + if err != nil { + return fmt.Errorf("failed to save downloaded file %s: %v", localFilePath, err) + } + + log.Printf("Downloaded file: %s to %s", remoteFilePath, localFilePath) + return nil +} diff --git a/server/main.go b/server/main.go index cc4c401..048fdf0 100644 --- a/server/main.go +++ b/server/main.go @@ -5,7 +5,9 @@ import ( "github.com/Vomitblood/cspj-application/server/internal/db" "github.com/Vomitblood/cspj-application/server/internal/http_server" + "github.com/Vomitblood/cspj-application/server/internal/log_watcher" "github.com/Vomitblood/cspj-application/server/internal/telegram" + "github.com/Vomitblood/cspj-application/server/internal/webdav" ) func main() { @@ -16,7 +18,16 @@ func main() { } defer db.DbPool.Close() - go telegram.TelegramBotInit() + // init webdav client + client := webdav.Init() + + // init telegram bot + tgBot := telegram.Init(client) + + // start log watcher + go log_watcher.WatchFile(tgBot) + + // http_server.ServeApi() }