mirror of
https://git.sr.ht/~phw/scotty
synced 2025-06-01 19:38:34 +02:00
131 lines
3.7 KiB
Go
131 lines
3.7 KiB
Go
/*
|
|
Copyright © 2023-2025 Philipp Wolfer <phw@uploadedlobster.com>
|
|
|
|
This file is part of Scotty.
|
|
|
|
Scotty is free software: you can redistribute it and/or modify it under the
|
|
terms of the GNU General Public License as published by the Free Software
|
|
Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
Scotty is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
Scotty. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package dump
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"go.uploadedlobster.com/scotty/internal/config"
|
|
"go.uploadedlobster.com/scotty/internal/i18n"
|
|
"go.uploadedlobster.com/scotty/internal/models"
|
|
)
|
|
|
|
type DumpBackend struct {
|
|
buffer io.ReadWriter
|
|
print bool // Whether to print the output to stdout
|
|
}
|
|
|
|
func (b *DumpBackend) Name() string { return "dump" }
|
|
|
|
func (b *DumpBackend) Options() []models.BackendOption {
|
|
return []models.BackendOption{{
|
|
Name: "file-path",
|
|
Label: i18n.Tr("File path"),
|
|
Type: models.String,
|
|
}, {
|
|
Name: "append",
|
|
Label: i18n.Tr("Append to file"),
|
|
Type: models.Bool,
|
|
Default: "true",
|
|
}}
|
|
}
|
|
|
|
func (b *DumpBackend) InitConfig(config *config.ServiceConfig) error {
|
|
filePath := config.GetString("file-path")
|
|
append := config.GetBool("append", true)
|
|
if strings.TrimSpace(filePath) != "" {
|
|
mode := os.O_WRONLY | os.O_CREATE
|
|
if !append {
|
|
mode |= os.O_TRUNC // Truncate the file if not appending
|
|
}
|
|
f, err := os.OpenFile(filePath, mode, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.buffer = f
|
|
b.print = false // If a file path is specified, we don't print to stdout
|
|
} else {
|
|
// If no file path is specified, use a bytes.Buffer for in-memory dumping
|
|
b.buffer = new(bytes.Buffer)
|
|
b.print = true // Print to stdout
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *DumpBackend) StartImport() error { return nil }
|
|
|
|
func (b *DumpBackend) FinishImport() error {
|
|
if b.print {
|
|
out := new(strings.Builder)
|
|
_, err := io.Copy(out, b.buffer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println(out.String())
|
|
}
|
|
|
|
// Close the io writer if it is closable
|
|
if closer, ok := b.buffer.(io.Closer); ok {
|
|
if err := closer.Close(); err != nil {
|
|
return fmt.Errorf("failed to close output file: %w", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *DumpBackend) ImportListens(ctx context.Context, export models.ListensResult, importResult models.ImportResult, progress chan models.TransferProgress) (models.ImportResult, error) {
|
|
for _, listen := range export.Items {
|
|
if err := ctx.Err(); err != nil {
|
|
return importResult, err
|
|
}
|
|
|
|
importResult.UpdateTimestamp(listen.ListenedAt)
|
|
importResult.ImportCount += 1
|
|
_, err := fmt.Fprintf(b.buffer, "🎶 %v: \"%v\" by %v (%v)\n",
|
|
listen.ListenedAt, listen.TrackName, listen.ArtistName(), listen.RecordingMBID)
|
|
if err != nil {
|
|
return importResult, err
|
|
}
|
|
progress <- models.TransferProgress{}.FromImportResult(importResult, false)
|
|
}
|
|
|
|
return importResult, nil
|
|
}
|
|
|
|
func (b *DumpBackend) ImportLoves(ctx context.Context, export models.LovesResult, importResult models.ImportResult, progress chan models.TransferProgress) (models.ImportResult, error) {
|
|
for _, love := range export.Items {
|
|
if err := ctx.Err(); err != nil {
|
|
return importResult, err
|
|
}
|
|
|
|
importResult.UpdateTimestamp(love.Created)
|
|
importResult.ImportCount += 1
|
|
_, err := fmt.Fprintf(b.buffer, "❤️ %v: \"%v\" by %v (%v)\n",
|
|
love.Created, love.TrackName, love.ArtistName(), love.RecordingMBID)
|
|
if err != nil {
|
|
return importResult, err
|
|
}
|
|
progress <- models.TransferProgress{}.FromImportResult(importResult, false)
|
|
}
|
|
|
|
return importResult, nil
|
|
}
|