From b037345b7b7a1f7678f75f57bd61939f2c3de50f Mon Sep 17 00:00:00 2001 From: K1ndWha1e Date: Fri, 9 Oct 2026 20:17:31 +0300 Subject: [PATCH] =?UTF-8?q?*write=5Fbook=5Ftags=5Freport:=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=20=D0=BB=D0=B8=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=20=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B5=20=D0=B8=20=D0=BF=D0=BE=D1=87=D0=B5=D0=BC=D1=83=20?= =?UTF-8?q?=D0=BD=D0=B5=D1=82=20(=D0=B7=D0=B0=D0=BF=D0=B0=D1=81=D0=BD?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=BC=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20=D0=BD=D0=B5=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=BB=D1=87=D0=B8=D1=82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- metadata/audiobook.v | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/metadata/audiobook.v b/metadata/audiobook.v index 6ae5f38..e96b82f 100644 --- a/metadata/audiobook.v +++ b/metadata/audiobook.v @@ -60,6 +60,14 @@ pub: remove_cover bool } +// Как прошла запись: на месте (тот же файл) или новым файлом поверх старого +pub struct WriteReport { +pub: + in_place bool + // Почему не удалось переписать на месте (пусто, если на месте) + fallback string +} + struct ParsedTag { mut: version u8 @@ -562,7 +570,7 @@ fn build_tag(parsed ParsedTag, t BookTags, opts WriteOptions) []u8 { // затем копируются обратно в исходный. Файл остаётся тем же (inode, владелец, права): // Audiobookshelf опознаёт файлы по inode, и замена файла новым путает его библиотеку. // Файл без ID3v2 тоже поддерживается — тэг просто ставится в начало -fn write_book_tags_impl(path string, t BookTags, opts WriteOptions) ! { +fn write_book_tags_impl(path string, t BookTags, opts WriteOptions) !WriteReport { parsed := parse_id3v2(path)! tag := build_tag(parsed, t, opts) @@ -595,6 +603,7 @@ fn write_book_tags_impl(path string, t BookTags, opts WriteOptions) ! { } copy_back(tmp_path, path, mut buf) or { // Исходный файл мог остаться наполовину переписанным — полная копия во временном + reason := err.msg() orig := os.stat(path) or { os.Stat{} } os.mv(tmp_path, path, overwrite: true) or { return error('${err}; новое содержимое сохранено в ${tmp_path}') @@ -605,9 +614,14 @@ fn write_book_tags_impl(path string, t BookTags, opts WriteOptions) ! { os.chown(path, int(orig.uid), int(orig.gid)) or {} } } - return + return WriteReport{ + fallback: reason + } } os.rm(tmp_path) or {} + return WriteReport{ + in_place: true + } } // Содержимое from — в существующий файл to (с обрезкой), не заменяя сам файл @@ -664,8 +678,13 @@ pub fn read_cover(path string) !Cover { // Запись тэгов книги в файл pub fn write_book_tags(path string, t BookTags, opts WriteOptions) ! { + write_book_tags_report(path, t, opts)! +} + +// То же, что write_book_tags, плюс отчёт: переписан ли файл на месте +pub fn write_book_tags_report(path string, t BookTags, opts WriteOptions) !WriteReport { mut box := PanicBox{} - guard_write_tags(path, t, opts, mut box) or { + report := guard_write_tags(path, t, opts, mut box) or { return if box.msg != '' { box.error() } else { @@ -675,6 +694,7 @@ pub fn write_book_tags(path string, t BookTags, opts WriteOptions) ! { if box.msg != '' { return box.error() } + return report } fn guard_read_tags(path string, mut box PanicBox) !FileTags { @@ -695,11 +715,11 @@ fn guard_read_cover(path string, mut box PanicBox) !Cover { return read_cover_impl(path)! } -fn guard_write_tags(path string, t BookTags, opts WriteOptions, mut box PanicBox) ! { +fn guard_write_tags(path string, t BookTags, opts WriteOptions, mut box PanicBox) !WriteReport { defer { if msg := recover() { box.msg = msg } } - write_book_tags_impl(path, t, opts)! + return write_book_tags_impl(path, t, opts)! }