From 9dbe5ee024468d15a478029ff38d41bd2d9507e5 Mon Sep 17 00:00:00 2001 From: Marcus Crane Date: Mon, 16 Dec 2024 21:49:10 +1300 Subject: [PATCH] Finish migration to log/slog Signed-off-by: Marcus Crane --- backend/db.go | 2 - backend/device.go | 57 ++++++++++++++------- backend/device_test.go | 12 ++--- backend/init.go | 17 +++--- backend/log.go | 12 +++-- backend/readwise.go | 108 ++++++++++++++++++++++++++++++--------- backend/readwise_test.go | 21 ++++---- cli/cli.go | 17 +++--- go.mod | 1 - go.sum | 3 -- 10 files changed, 167 insertions(+), 83 deletions(-) diff --git a/backend/db.go b/backend/db.go index 5b072f5..832468f 100644 --- a/backend/db.go +++ b/backend/db.go @@ -2,7 +2,6 @@ package backend import ( "github.com/glebarez/sqlite" - "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -11,7 +10,6 @@ var Conn *gorm.DB func OpenConnection(filepath string) error { conn, err := gorm.Open(sqlite.Open(filepath), &gorm.Config{}) if err != nil { - logrus.WithError(err).WithField("filepath", filepath).Error("Failed to open DB connection") return err } Conn = conn diff --git a/backend/device.go b/backend/device.go index 71de1fa..5c755a2 100644 --- a/backend/device.go +++ b/backend/device.go @@ -2,10 +2,9 @@ package backend import ( "fmt" + "log/slog" "strings" - "github.com/sirupsen/logrus" - "github.com/pgaskin/koboutils/v2/kobo" ) @@ -155,14 +154,20 @@ func (Bookmark) TableName() string { return "Bookmark" } -func GetKoboMetadata(detectedPaths []string) []Kobo { +func GetKoboMetadata(detectedPaths []string, logger *slog.Logger) []Kobo { var kobos []Kobo for _, path := range detectedPaths { _, _, deviceId, err := kobo.ParseKoboVersion(path) if err != nil { - logrus.WithField("kobo_path", path).WithError(err).Error("Failed to parse Kobo version") + logger.Error("Failed to parse Kobo version", + slog.String("error", err.Error()), + slog.String("kobo_path", path), + ) } - logrus.WithField("device_id", deviceId).Info("Found an attached device") + logger.Info("Found attached device", + slog.String("device_id", deviceId), + slog.String("kobo_path", path), + ) device, found := kobo.DeviceByID(deviceId) if found { kobos = append(kobos, Kobo{ @@ -187,7 +192,9 @@ func GetKoboMetadata(detectedPaths []string) []Kobo { }) continue } - logrus.WithField("device_id", deviceId).Warn("Found a device that isn't officially supported but will likely still operate just fine") + logger.Warn("Found a device that isn't officially supported but will likely still operate just fine", + slog.String("device_id", deviceId), + ) // We can handle unsupported Kobos in future but at present, there are none kobos = append(kobos, Kobo{ MntPath: path, @@ -197,55 +204,67 @@ func GetKoboMetadata(detectedPaths []string) []Kobo { return kobos } -func (k *Kobo) ListDeviceContent(includeStoreBought bool) ([]Content, error) { +func (k *Kobo) ListDeviceContent(includeStoreBought bool, logger *slog.Logger) ([]Content, error) { var content []Content - logrus.Debug("Retrieving content list from device") + logger.Debug("Retrieving content list from device") result := Conn.Where(&Content{ContentType: "6", VolumeIndex: -1}) if !includeStoreBought { result = result.Where("ContentID LIKE '%file:///%'") } result = result.Order("___PercentRead desc, title asc").Find(&content) if result.Error != nil { - logrus.WithError(result.Error).Error("Failed to retrieve content from device") + logger.Error("Failed to retrieve content from device", + slog.String("error", result.Error.Error()), + ) return nil, result.Error } - logrus.WithField("content_count", len(content)).Debug("Successfully retrieved device content") + logger.Debug("Successfully retrieved device content", + slog.Int("content_count", len(content)), + ) return content, nil } -func (k *Kobo) ListDeviceBookmarks(includeStoreBought bool) ([]Bookmark, error) { +func (k *Kobo) ListDeviceBookmarks(includeStoreBought bool, logger *slog.Logger) ([]Bookmark, error) { var bookmarks []Bookmark - logrus.Debug("Retrieving bookmarks from device") + logger.Debug("Retrieving bookmarks from device") result := Conn if !includeStoreBought { result = result.Where("VolumeID LIKE '%file:///%'") } result = result.Order("VolumeID ASC, ChapterProgress ASC").Find(&bookmarks).Limit(1) if result.Error != nil { - logrus.WithError(result.Error).Error("Failed to retrieve bookmarks from device") + logger.Error("Failed to retrieve bookmarks from device", + slog.String("error", result.Error.Error()), + ) return nil, result.Error } - logrus.WithField("bookmark_count", len(bookmarks)).Debug("Successfully retrieved device bookmarks") + logger.Debug("Successfully retrieved device bookmarks", + slog.Int("bookmark_count", len(bookmarks)), + ) return bookmarks, nil } -func (k *Kobo) BuildContentIndex(content []Content) map[string]Content { - logrus.Debug("Building an index out of device content") +func (k *Kobo) BuildContentIndex(content []Content, logger *slog.Logger) map[string]Content { + logger.Debug("Building an index out of device content") contentIndex := make(map[string]Content) for _, item := range content { contentIndex[item.ContentID] = item } - logrus.WithField("index_count", len(contentIndex)).Debug("Built content index") + logger.Debug("Built content index", + slog.Int("index_count", len(contentIndex)), + ) return contentIndex } -func (k *Kobo) CountDeviceBookmarks() HighlightCounts { +func (k *Kobo) CountDeviceBookmarks(logger *slog.Logger) HighlightCounts { var totalCount int64 var officialCount int64 var sideloadedCount int64 result := Conn.Model(&Bookmark{}).Count(&totalCount) if result.Error != nil { - logrus.WithError(result.Error).Error("Failed to count bookmarks on device") + logger.Error("Failed to count bookmarks on device", + slog.String("error", result.Error.Error()), + ) } Conn.Model(&Bookmark{}).Where("VolumeID LIKE '%file:///%'").Count(&sideloadedCount) Conn.Model(&Bookmark{}).Where("VolumeID NOT LIKE '%file:///%'").Count(&officialCount) diff --git a/backend/device_test.go b/backend/device_test.go index da4f77b..178a4f5 100644 --- a/backend/device_test.go +++ b/backend/device_test.go @@ -1,11 +1,11 @@ package backend import ( + "log/slog" "os" "path/filepath" "testing" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) @@ -22,20 +22,18 @@ func setupTmpKobo(dir string, deviceId string) string { content := []byte(deviceId) err := os.Mkdir(filepath.Join(dir, ".kobo"), 0777) if err != nil { - logrus.Fatal(err) - return "" + panic(err) } tmpfn := filepath.Join(dir, ".kobo", "version") if err := os.WriteFile(tmpfn, content, 0666); err != nil { - logrus.Fatal(err) - return "" + panic(err) } return dir } func TestGetKoboMetadata_HandleNoDevices(t *testing.T) { var expected []Kobo - actual := GetKoboMetadata([]string{}) + actual := GetKoboMetadata([]string{}, slog.New(&discardHandler{})) assert.Equal(t, expected, actual) } @@ -85,6 +83,6 @@ func TestGetKoboMetadata_HandleConnectedDevices(t *testing.T) { }, } detectedPaths := []string{fakeLibraVolume, fakeMiniVolume, fakeElipsaVolume, fakeClara2EVolume, fakeUnknownVolume} - actual := GetKoboMetadata(detectedPaths) + actual := GetKoboMetadata(detectedPaths, slog.New(&discardHandler{})) assert.Equal(t, expected, actual) } diff --git a/backend/init.go b/backend/init.go index 1e7daae..7457df9 100644 --- a/backend/init.go +++ b/backend/init.go @@ -51,6 +51,7 @@ func StartBackend(ctx *context.Context, version string, portable bool, logger *s RuntimeContext: ctx, Settings: settings, Readwise: &Readwise{ + logger: logger, UserAgent: fmt.Sprintf(UserAgentFmt, version), }, Kobo: &Kobo{}, @@ -122,7 +123,7 @@ func (b *Backend) DetectKobos() []Kobo { b.logger.Error("Failed to detect any connected Kobos") panic(err) } - kobos := GetKoboMetadata(connectedKobos) + kobos := GetKoboMetadata(connectedKobos, b.logger) b.logger.Info("Found one or more kobos", "count", len(kobos), ) @@ -159,6 +160,10 @@ func (b *Backend) SelectKobo(devicePath string) error { } } if err := OpenConnection(b.SelectedKobo.DbPath); err != nil { + b.logger.Error("Failed to open DB connection", + slog.String("error", err.Error()), + slog.String("db_path", b.SelectedKobo.DbPath), + ) return err } return nil @@ -185,7 +190,7 @@ func (b *Backend) PromptForLocalDBPath() error { } func (b *Backend) ForwardToReadwise() (int, error) { - highlightBreakdown := b.Kobo.CountDeviceBookmarks() + highlightBreakdown := b.Kobo.CountDeviceBookmarks(b.logger) slog.Info("Got highlight counts from device", slog.Int("highlight_count_sideload", int(highlightBreakdown.Sideloaded)), slog.Int("highlight_count_official", int(highlightBreakdown.Official)), @@ -200,22 +205,22 @@ func (b *Backend) ForwardToReadwise() (int, error) { slog.Error("Tried to submit highlights with no sideloaded highlights + store-bought syncing disabled. Result is that no highlights would be fetched.") return 0, fmt.Errorf("You have disabled store-bought syncing but you don't have any sideloaded highlights either. This combination means there are no highlights left to be synced.") } - content, err := b.Kobo.ListDeviceContent(includeStoreBought) + content, err := b.Kobo.ListDeviceContent(includeStoreBought, b.logger) if err != nil { slog.Error("Received an error trying to list content from device", slog.String("error", err.Error()), ) return 0, err } - contentIndex := b.Kobo.BuildContentIndex(content) - bookmarks, err := b.Kobo.ListDeviceBookmarks(includeStoreBought) + contentIndex := b.Kobo.BuildContentIndex(content, b.logger) + bookmarks, err := b.Kobo.ListDeviceBookmarks(includeStoreBought, b.logger) if err != nil { slog.Error("Received an error trying to list bookmarks from device", slog.String("error", err.Error()), ) return 0, err } - payload, err := BuildPayload(bookmarks, contentIndex) + payload, err := BuildPayload(bookmarks, contentIndex, b.logger) if err != nil { slog.Error("Received an error trying to build Readwise payload", slog.String("error", err.Error()), diff --git a/backend/log.go b/backend/log.go index d72244b..c55cd73 100644 --- a/backend/log.go +++ b/backend/log.go @@ -1,12 +1,11 @@ package backend import ( + "context" "fmt" "log/slog" "os" "time" - - "github.com/sirupsen/logrus" ) var logFileHandle *os.File @@ -18,8 +17,6 @@ func StartLogger(portable bool, level slog.Leveler) (*slog.Logger, error) { if err != nil { panic("Failed to create location to store logfiles") } - - logrus.SetFormatter(&logrus.JSONFormatter{}) file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return &slog.Logger{}, err @@ -35,3 +32,10 @@ func StartLogger(portable bool, level slog.Leveler) (*slog.Logger, error) { func CloseLogFile() { logFileHandle.Close() } + +// Dummy until real handler ships in Go 1.24 +type discardHandler struct { + slog.TextHandler +} + +func (d *discardHandler) Enabled(context.Context, slog.Level) bool { return false } diff --git a/backend/readwise.go b/backend/readwise.go index 63d2c75..34b05f3 100644 --- a/backend/readwise.go +++ b/backend/readwise.go @@ -6,14 +6,13 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/http/httputil" "net/url" "path" "strings" "time" - - "github.com/sirupsen/logrus" ) const ( @@ -52,6 +51,7 @@ type BookListEntry struct { } type Readwise struct { + logger *slog.Logger UserAgent string } @@ -70,7 +70,7 @@ func (r *Readwise) CheckTokenValidity(token string) error { if resp.StatusCode != 204 { return errors.New(resp.Status) } - logrus.Info("Successfully validated token against the Readwise API") + r.logger.Info("Successfully validated token against the Readwise API") return nil } @@ -98,13 +98,18 @@ func (r *Readwise) SendBookmarks(payloads []Response, token string) (int, error) defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err == nil { - logrus.WithFields(logrus.Fields{"status_code": resp.StatusCode, "response": string(body)}).Error("Received a non-200 response from Readwise") + r.logger.Error("Received a non-200 response from Readwise", + slog.Int("status_code", resp.StatusCode), + slog.String("response", string(body)), + ) } return 0, fmt.Errorf("received a non-200 status code from Readwise: code %d", resp.StatusCode) } submittedHighlights += len(payload.Highlights) } - logrus.WithField("batch_count", len(payloads)).Info("Successfully sent bookmarks to Readwise") + r.logger.Info("Successfully sent bookmarks to Readwise", + slog.Int("batch_count", len(payloads)), + ) return submittedHighlights, nil } @@ -117,7 +122,9 @@ func (r *Readwise) RetrieveUploadedBooks(token string) (BookListResponse, error) client := http.Client{} remoteURL, err := url.Parse(BooksEndpoint) if err != nil { - logrus.WithError(err).Error("Failed to parse URL for Readwise book upload endpoint") + r.logger.Error("Failed to parse URL for Readwise book upload endpoint", + slog.String("error", err.Error()), + ) } request := http.Request{ Method: "GET", @@ -126,7 +133,10 @@ func (r *Readwise) RetrieveUploadedBooks(token string) (BookListResponse, error) } res, err := client.Do(&request) if err != nil { - logrus.WithError(err).WithField("status_code", res.StatusCode).Error("An unexpected error occurred while retrieving uploads from Readwise") + r.logger.Error("An unexpected error occurred while retrieving uploads from Readwise", + slog.String("error", err.Error()), + slog.Int("status_code", res.StatusCode), + ) return bookList, err } defer func(Body io.ReadCloser) { @@ -136,24 +146,37 @@ func (r *Readwise) RetrieveUploadedBooks(token string) (BookListResponse, error) }(res.Body) b, err := httputil.DumpResponse(res, true) if err != nil { - logrus.WithError(err).Error("Encountered an error while dumping response from Readwise") + r.logger.Error("Encountered an error while dumping response from Readwise", + slog.String("error", err.Error()), + ) return bookList, err } if res.StatusCode != 200 { - logrus.WithFields(logrus.Fields{"status": res.StatusCode, "body": string(b)}).Error("Received a non-200 response from Readwise") + r.logger.Error("Received a non-200 response from Readwise", + slog.Int("status", res.StatusCode), + slog.String("body", string(b)), + ) return bookList, err } body, err := io.ReadAll(res.Body) if err != nil { - logrus.WithError(err).Error("Failed to parse response from Readwise") + r.logger.Error("Failed to parse response from Readwise", + slog.String("error", err.Error()), + ) return bookList, err } err = json.Unmarshal(body, &bookList) if err != nil { - logrus.WithError(err).WithFields(logrus.Fields{"status": res.StatusCode, "body": string(b)}).Error("Failed to unmarshal response from Readwise") + r.logger.Error("Failed to unmarshal response from Readwise", + slog.String("error", err.Error()), + slog.Int("status", res.StatusCode), + slog.String("body", string(b)), + ) return bookList, err } - logrus.WithField("book_count", bookList.Count).Info("Successfully retrieved books from Readwise API") + r.logger.Info("Successfully retrieved books from Readwise API", + slog.Int("book_count", bookList.Count), + ) return bookList, nil } @@ -181,14 +204,17 @@ func (r *Readwise) UploadCover(encodedCover string, bookId int, token string) er defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err == nil { - logrus.WithFields(logrus.Fields{"status_code": resp.StatusCode, "response": string(body)}).Error("Received a non-200 response from Readwise") + r.logger.Error("Received a non-200 response from Readwise", + slog.Int("status", resp.StatusCode), + slog.String("body", string(body)), + ) } return fmt.Errorf("failed to upload cover for book with id %d", bookId) } return nil } -func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Response, error) { +func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content, logger *slog.Logger) ([]Response, error) { var payloads []Response var currentBatch Response for count, entry := range bookmarks { @@ -199,17 +225,30 @@ func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Resp currentBatch = Response{} } source := contentIndex[entry.VolumeID] - logrus.WithField("title", source.Title).Debug("Parsing highlight") + logger.Debug("Parsing highlight", + slog.String("title", source.Title), + ) var createdAt string if entry.DateCreated == "" { - logrus.WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID}).Warn("No date created for bookmark. Defaulting to date last modified.") + logger.Warn("No date created for bookmark. Defaulting to date last modified.", + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + ) if entry.DateModified == "" { - logrus.WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID}).Warn("No date modified for bookmark. Default to current date.") + logger.Warn("No date modified for bookmark. Default to current date.", + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + ) createdAt = time.Now().Format("2006-01-02T15:04:05-07:00") } else { t, err := time.Parse("2006-01-02T15:04:05Z", entry.DateModified) if err != nil { - logrus.WithError(err).WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID, "date_modified": entry.DateModified}).Error("Failed to parse a valid timestamp from date modified field") + logger.Error("Failed to parse a valid timestamp from date modified field", + slog.String("error", err.Error()), + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + slog.String("date_modified", entry.DateModified), + ) return []Response{}, err } createdAt = t.Format("2006-01-02T15:04:05-07:00") @@ -217,7 +256,12 @@ func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Resp } else { t, err := time.Parse("2006-01-02T15:04:05.000", entry.DateCreated) if err != nil { - logrus.WithError(err).WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID, "date_modified": entry.DateModified}).Error("Failed to parse a valid timestamp from date created field") + logger.Error("Failed to parse a valid timestamp from date created field", + slog.String("error", err.Error()), + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + slog.String("date_modified", entry.DateModified), + ) return []Response{}, err } createdAt = t.Format("2006-01-02T15:04:05-07:00") @@ -231,7 +275,10 @@ func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Resp } if entry.Annotation == "" && text == "" { // This state should be impossible but stranger things have happened so worth a sanity check - logrus.WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID}).Warn("Found an entry with neither highlighted text nor an annotation so skipping entry") + logger.Warn("Found an entry with neither highlighted text nor an annotation so skipping entry", + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + ) continue } if source.Title == "" { @@ -244,11 +291,17 @@ func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Resp // or even just arbitrary strings. Given we don't set a title here, we will use the Readwise fallback which is to add // these highlights to a book called "Quotes" and let the user figure out their metadata situation. That reminds me though: // TODO: Test exports with non-epub files - logrus.WithError(err).WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID}).Warn("Failed to retrieve epub title. This is not a hard requirement so sending with a dummy title.") + logger.Warn("Failed to retrieve epub title. This is not a hard requirement so sending with a dummy title.", + slog.String("error", err.Error()), + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + ) goto sendhighlight } filename := path.Base(sourceFile.Path) - logrus.WithField("filename", filename).Debug("No source title. Constructing title from filename") + logger.Debug("No source title. Constructing title from filename", + slog.String("filename", filename), + ) source.Title = strings.TrimSuffix(filename, ".epub") } sendhighlight: @@ -266,10 +319,17 @@ func BuildPayload(bookmarks []Bookmark, contentIndex map[string]Content) ([]Resp } currentBatch.Highlights = append(currentBatch.Highlights, highlight) } - logrus.WithFields(logrus.Fields{"title": source.Title, "volume_id": entry.VolumeID, "chunks": len(highlightChunks)}).Debug("Successfully compiled highlights for book") + logger.Debug("Successfully compiled highlights for book", + slog.String("title", source.Title), + slog.String("volume_id", entry.VolumeID), + slog.Int("chunks", len(highlightChunks)), + ) } payloads = append(payloads, currentBatch) - logrus.WithFields(logrus.Fields{"highlight_count": len(currentBatch.Highlights), "batch_count": len(payloads)}).Info("Successfully parsed highlights") + logger.Info("Succcessfully parsed highlights", + slog.Int("highlight_count", len(currentBatch.Highlights)), + slog.Int("batch_count", len(payloads)), + ) return payloads, nil } diff --git a/backend/readwise_test.go b/backend/readwise_test.go index 689e920..2806f4c 100644 --- a/backend/readwise_test.go +++ b/backend/readwise_test.go @@ -2,6 +2,7 @@ package backend import ( "fmt" + "log/slog" "strings" "testing" @@ -12,7 +13,7 @@ func TestBuildPayload_NoBookmarks(t *testing.T) { var expected Response var contentIndex map[string]Content var bookmarks []Bookmark - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -32,7 +33,7 @@ func TestBuildPayload_BookmarksPresent(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", Text: "Hello World", DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -52,7 +53,7 @@ func TestBuildPayload_HandleAnnotationOnly(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -72,7 +73,7 @@ func TestBuildPayload_TitleFallback(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", Text: "Hello World", DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -90,7 +91,7 @@ func TestBuildPayload_TitleFallbackFailure(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "\t", Text: "Hello World", DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -108,7 +109,7 @@ func TestBuildPayload_NoHighlightDateCreated(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "\t", Text: "Hello World", DateCreated: "", Annotation: "Making a note here", DateModified: "2006-01-02T15:04:05Z"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -117,7 +118,7 @@ func TestBuildPayload_NoHighlightDateAtAll(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "abc123", Text: "Hello World", Annotation: "Making a note here"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, actual[0].Highlights[0].SourceURL, bookmarks[0].VolumeID) assert.Equal(t, actual[0].Highlights[0].Text, bookmarks[0].Text) assert.Equal(t, actual[0].Highlights[0].Note, bookmarks[0].Annotation) @@ -130,7 +131,7 @@ func TestBuildPayload_SkipMalformedBookmarks(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", DateCreated: "2006-01-02T15:04:05.000"}, } - var actual, _ = BuildPayload(bookmarks, contentIndex) + var actual, _ = BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.Equal(t, expected, actual[0]) } @@ -176,7 +177,7 @@ func TestBuildPayload_LongHighlightChunks(t *testing.T) { bookmarks := []Bookmark{ {VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", Text: text, DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}, } - actual, err := BuildPayload(bookmarks, contentIndex) + actual, err := BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.NoError(t, err) assert.Equal(t, expected, actual[0]) } @@ -188,7 +189,7 @@ func TestExcessiveHighlightAmounts(t *testing.T) { for i := 0; i < 4002; i++ { bookmarks = append(bookmarks, Bookmark{VolumeID: "mnt://kobo/blah/Good Book - An Author.epub", Text: fmt.Sprintf("hi%d", i), DateCreated: "2006-01-02T15:04:05.000", Annotation: "Making a note here"}) } - actual, err := BuildPayload(bookmarks, contentIndex) + actual, err := BuildPayload(bookmarks, contentIndex, slog.New(&discardHandler{})) assert.NoError(t, err) assert.Equal(t, expected, len(actual)) } diff --git a/cli/cli.go b/cli/cli.go index c41adb3..f3c95f1 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -3,12 +3,10 @@ package cli import ( "context" "fmt" - "log" "log/slog" "os" "github.com/marcus-crane/october/backend" - "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -40,7 +38,10 @@ func Invoke(isPortable bool, version string, logger *slog.Logger) { Usage: "sync kobo highlights to readwise", Action: func(c *cli.Context) error { ctx := context.Background() - b := backend.StartBackend(&ctx, version, isPortable, logger) + b, err := backend.StartBackend(&ctx, version, isPortable, logger) + if err != nil { + return err + } if b.Settings.ReadwiseToken == "" { return fmt.Errorf("no readwise token was configured. please set this up using the gui as the cli does not support this yet") } @@ -51,15 +52,16 @@ func Invoke(isPortable bool, version string, logger *slog.Logger) { if len(kobos) > 1 { return fmt.Errorf("cli only supports one connected kobo at a time") } - err := b.SelectKobo(kobos[0].MntPath) - if err != nil { + if err := b.SelectKobo(kobos[0].MntPath); err != nil { return fmt.Errorf("an error occurred trying to connect to the kobo at %s", kobos[0].MntPath) } num, err := b.ForwardToReadwise() if err != nil { return err } - logrus.Infof("Successfully synced %d highlights to Readwise", num) + logger.Info("Successfully synced highlights to Readwise", + slog.Int("count", num), + ) return nil }, }, @@ -80,6 +82,7 @@ func Invoke(isPortable bool, version string, logger *slog.Logger) { err := app.Run(args) if err != nil { - log.Fatal(err) + logger.Error(err.Error()) + os.Exit(1) } } diff --git a/go.mod b/go.mod index 08dd004..b2f546c 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/glebarez/sqlite v1.10.0 github.com/pgaskin/koboutils/v2 v2.2.0 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.0 github.com/wailsapp/wails/v2 v2.9.2 diff --git a/go.sum b/go.sum index 0884227..f7ab434 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,6 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -103,7 +101,6 @@ golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=