package editor import ( "context" "encoding/xml" "errors" "fmt" "io" "log/slog" "sync" "time" "code.capytal.cc/capytal/comicverse/editor/epub" "code.capytal.cc/capytal/comicverse/editor/storage" "code.capytal.cc/loreddev/x/tinyssert" "github.com/google/uuid" "golang.org/x/text/language" ) func New( storage storage.Storage, logger *slog.Logger, assert tinyssert.Assertions, ) *Editor { assert.NotZero(storage) assert.NotZero(logger) return &Editor{ storage: storage, log: logger, assert: assert, } } type Editor struct { storage storage.Storage ctx context.Context log *slog.Logger assert tinyssert.Assertions } func (e *Editor) New(id uuid.UUID, title string, lang language.Tag) (*Container, error) { f := fmt.Sprintf("%s/content.opf", id) if e.storage.Exists(f) { return nil, ErrAlreadyExists } pub := &Container{ id: id, pkg: epub.Package{ Metadata: epub.Metadata{ ID: fmt.Sprintf("comicverse:%s", id), Title: title, Language: lang, Date: time.Now(), Modified: time.Now(), }, }, log: e.log.WithGroup(fmt.Sprintf("publication:%s", id)), assert: e.assert, storage: storage.WithRoot(id.String(), e.storage), } err := pub.Flush() if err != nil { return nil, fmt.Errorf("editor: unable to flush changes of publication: %w", err) } return pub, nil } func (e *Editor) Open(id uuid.UUID) (*Container, error) { content, err := e.storage.Open(fmt.Sprintf("%s/content.opf", id)) if errors.Is(err, storage.ErrNotExists) { return nil, ErrNotExists } else if err != nil { return nil, fmt.Errorf("editor: unable to open package: %w", err) } b, err := io.ReadAll(content) if err != nil { return nil, fmt.Errorf("editor: unable to read contents of package: %w", err) } var pkg epub.Package err = xml.Unmarshal(b, &pkg) if err != nil { return nil, fmt.Errorf("editor: unable to decode xml of package: %w", err) } c := &Container{ id: id, pkg: pkg, log: e.log.WithGroup(fmt.Sprintf("publication:%s", id)), assert: e.assert, storage: storage.WithRoot(id.String(), e.storage), } return c, nil } var ( ErrAlreadyExists = errors.New("editor: file already exists") ErrNotExists = errors.New("editor: file doesn't exist") )