diff --git a/internal/cmd/export.go b/internal/cmd/export.go index 6484a3e0e..74eaaabf8 100644 --- a/internal/cmd/export.go +++ b/internal/cmd/export.go @@ -37,7 +37,9 @@ func exportHandler(cmd *cobra.Command, args []string) { // Make sure destination directory exist dstDir := fp.Dir(args[0]) - os.MkdirAll(dstDir, os.ModePerm) + if err := os.MkdirAll(dstDir, os.ModePerm); err != nil { + cError.Printf("Error crating destination directory: %s", err) + } // Create destination file dstFile, err := os.Create(args[0]) diff --git a/internal/cmd/utils.go b/internal/cmd/utils.go index b50999540..bd7788c39 100644 --- a/internal/cmd/utils.go +++ b/internal/cmd/utils.go @@ -13,21 +13,19 @@ import ( "github.com/fatih/color" "github.com/go-shiori/shiori/internal/model" - "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" ) var ( - cIndex = color.New(color.FgHiCyan) - cSymbol = color.New(color.FgHiMagenta) - cTitle = color.New(color.FgHiGreen).Add(color.Bold) - cReadTime = color.New(color.FgHiMagenta) - cURL = color.New(color.FgHiYellow) - cExcerpt = color.New(color.FgHiWhite) - cTag = color.New(color.FgHiBlue) - - cInfo = color.New(color.FgHiCyan) - cError = color.New(color.FgHiRed) - cWarning = color.New(color.FgHiYellow) + cIndex = color.New(color.FgHiCyan) + cSymbol = color.New(color.FgHiMagenta) + cTitle = color.New(color.FgHiGreen).Add(color.Bold) + cURL = color.New(color.FgHiYellow) + cExcerpt = color.New(color.FgHiWhite) + cTag = color.New(color.FgHiBlue) + + cInfo = color.New(color.FgHiCyan) + cError = color.New(color.FgHiRed) errInvalidIndex = errors.New("Index is not valid") ) @@ -130,7 +128,7 @@ func openBrowser(url string) error { } func getTerminalWidth() int { - width, _, _ := terminal.GetSize(int(os.Stdin.Fd())) + width, _, _ := term.GetSize(int(os.Stdin.Fd())) return width } diff --git a/internal/core/processing.go b/internal/core/processing.go index e15a5e209..345a83944 100644 --- a/internal/core/processing.go +++ b/internal/core/processing.go @@ -71,7 +71,7 @@ func ProcessBookmark(req ProcessRequest) (model.Bookmark, bool, error) { nurl, err := url.Parse(book.URL) if err != nil { - fmt.Errorf("Failed to parse url: %v", err) + return book, true, fmt.Errorf("Failed to parse url: %v", err) } article, err := readability.FromReader(readabilityInput, nurl) diff --git a/internal/database/mysql.go b/internal/database/mysql.go index 3176396a8..73ed726c2 100644 --- a/internal/database/mysql.go +++ b/internal/database/mysql.go @@ -3,6 +3,7 @@ package database import ( "database/sql" "fmt" + "log" "strings" "time" @@ -33,7 +34,9 @@ func OpenMySQLDatabase(connString string) (mysqlDB *MySQLDatabase, err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } mysqlDB = nil err = panicErr @@ -102,7 +105,9 @@ func (db *MySQLDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []mo defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } result = []model.Bookmark{} err = panicErr @@ -192,7 +197,9 @@ func (db *MySQLDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []mo tag.ID = int(tagID64) } - stmtInsertBookTag.Exec(tag.ID, book.ID) + if _, err := stmtInsertBookTag.Exec(tag.ID, book.ID); err != nil { + log.Printf("error during insert: %s", err) + } } newTags = append(newTags, tag) @@ -458,7 +465,9 @@ func (db *MySQLDatabase) DeleteBookmarks(ids ...int) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } @@ -507,7 +516,9 @@ func (db *MySQLDatabase) GetBookmark(id int, url string) (model.Bookmark, bool) } book := model.Bookmark{} - db.Get(&book, query, args...) + if err := db.Get(&book, query, args...); err != nil { + log.Printf("error during db.get: %s", err) + } return book, book.ID != 0 } @@ -562,9 +573,12 @@ func (db *MySQLDatabase) GetAccounts(opts GetAccountsOptions) ([]model.Account, // Returns the account and boolean whether it's exist or not. func (db *MySQLDatabase) GetAccount(username string) (model.Account, bool) { account := model.Account{} - db.Get(&account, `SELECT + if err := db.Get(&account, `SELECT id, username, password, owner FROM account WHERE username = ?`, - username) + username, + ); err != nil { + log.Printf("error during db.get: %s", err) + } return account, account.ID != 0 } @@ -581,7 +595,9 @@ func (db *MySQLDatabase) DeleteAccounts(usernames ...string) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } diff --git a/internal/database/pg.go b/internal/database/pg.go index 37512006d..78bf39018 100644 --- a/internal/database/pg.go +++ b/internal/database/pg.go @@ -3,6 +3,7 @@ package database import ( "database/sql" "fmt" + "log" "strings" "time" @@ -32,8 +33,9 @@ func OpenPGDatabase(connString string) (pgDB *PGDatabase, err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } pgDB = nil err = panicErr } @@ -98,7 +100,9 @@ func (db *PGDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []model defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } result = []model.Bookmark{} err = panicErr @@ -188,7 +192,9 @@ func (db *PGDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []model tag.ID = int(tagID64) } - stmtInsertBookTag.Exec(tag.ID, book.ID) + if _, err := stmtInsertBookTag.Exec(tag.ID, book.ID); err != nil { + log.Printf("error during insert: %s", err) + } } newTags = append(newTags, tag) @@ -237,7 +243,7 @@ func (db *PGDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookmark, // Add where clause for search keyword if opts.Keyword != "" { query += ` AND ( - url LIKE :lkw OR + url LIKE :lkw OR MATCH(title, excerpt, content) AGAINST (:kw IN BOOLEAN MODE) )` @@ -315,7 +321,8 @@ func (db *PGDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookmark, } // Expand query, because some of the args might be an array - query, args, err := sqlx.Named(query, arg) + var err error + query, args, _ := sqlx.Named(query, arg) query, args, err = sqlx.In(query, args...) if err != nil { return nil, fmt.Errorf("failed to expand query: %v", err) @@ -330,10 +337,10 @@ func (db *PGDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookmark, } // Fetch tags for each bookmarks - stmtGetTags, err := db.Preparex(`SELECT t.id, t.name - FROM bookmark_tag bt + stmtGetTags, err := db.Preparex(`SELECT t.id, t.name + FROM bookmark_tag bt LEFT JOIN tag t ON bt.tag_id = t.id - WHERE bt.bookmark_id = $1 + WHERE bt.bookmark_id = $1 ORDER BY t.name`) if err != nil { return nil, fmt.Errorf("failed to prepare tag query: %v", err) @@ -369,7 +376,7 @@ func (db *PGDatabase) GetBookmarksCount(opts GetBookmarksOptions) (int, error) { // Add where clause for search keyword if opts.Keyword != "" { query += ` AND ( - url LIKE :lurl OR + url LIKE :lurl OR MATCH(title, excerpt, content) AGAINST (:kw IN BOOLEAN MODE) )` @@ -431,7 +438,8 @@ func (db *PGDatabase) GetBookmarksCount(opts GetBookmarksOptions) (int, error) { } // Expand query, because some of the args might be an array - query, args, err := sqlx.Named(query, arg) + var err error + query, args, _ := sqlx.Named(query, arg) query, args, err = sqlx.In(query, args...) if err != nil { return 0, fmt.Errorf("failed to expand query: %v", err) @@ -460,8 +468,9 @@ func (db *PGDatabase) DeleteBookmarks(ids ...int) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } }() @@ -499,7 +508,7 @@ func (db *PGDatabase) DeleteBookmarks(ids ...int) (err error) { func (db *PGDatabase) GetBookmark(id int, url string) (model.Bookmark, bool) { args := []interface{}{id} query := `SELECT - id, url, title, excerpt, author, public, + id, url, title, excerpt, author, public, content, html, modified, content <> '' has_content FROM bookmark WHERE id = $1` @@ -509,7 +518,9 @@ func (db *PGDatabase) GetBookmark(id int, url string) (model.Bookmark, bool) { } book := model.Bookmark{} - db.Get(&book, query, args...) + if err := db.Get(&book, query, args...); err != nil { + log.Printf("error during db.get: %s", err) + } return book, book.ID != 0 } @@ -564,9 +575,12 @@ func (db *PGDatabase) GetAccounts(opts GetAccountsOptions) ([]model.Account, err // Returns the account and boolean whether it's exist or not. func (db *PGDatabase) GetAccount(username string) (model.Account, bool) { account := model.Account{} - db.Get(&account, `SELECT + if err := db.Get(&account, `SELECT id, username, password, owner FROM account WHERE username = $1`, - username) + username, + ); err != nil { + log.Printf("error during db.get: %s", err) + } return account, account.ID != 0 } @@ -583,8 +597,9 @@ func (db *PGDatabase) DeleteAccounts(usernames ...string) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } }() @@ -605,8 +620,8 @@ func (db *PGDatabase) DeleteAccounts(usernames ...string) (err error) { // GetTags fetch list of tags and their frequency. func (db *PGDatabase) GetTags() ([]model.Tag, error) { tags := []model.Tag{} - query := `SELECT bt.tag_id id, t.name, COUNT(bt.tag_id) n_bookmarks - FROM bookmark_tag bt + query := `SELECT bt.tag_id id, t.name, COUNT(bt.tag_id) n_bookmarks + FROM bookmark_tag bt LEFT JOIN tag t ON bt.tag_id = t.id GROUP BY bt.tag_id, t.name ORDER BY t.name` diff --git a/internal/database/sqlite.go b/internal/database/sqlite.go index af7d699ad..3f4c406bd 100644 --- a/internal/database/sqlite.go +++ b/internal/database/sqlite.go @@ -3,6 +3,7 @@ package database import ( "database/sql" "fmt" + "log" "strings" "time" @@ -31,8 +32,9 @@ func OpenSQLiteDatabase(databasePath string) (sqliteDB *SQLiteDatabase, err erro defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } sqliteDB = nil err = panicErr } @@ -74,8 +76,12 @@ func OpenSQLiteDatabase(databasePath string) (sqliteDB *SQLiteDatabase, err erro tx.MustExec(`CREATE VIRTUAL TABLE IF NOT EXISTS bookmark_content USING fts5(title, content, html, docid)`) // Alter table if needed - tx.Exec(`ALTER TABLE account ADD COLUMN owner INTEGER NOT NULL DEFAULT 0`) - tx.Exec(`ALTER TABLE bookmark ADD COLUMN public INTEGER NOT NULL DEFAULT 0`) + if _, err := tx.Exec(`ALTER TABLE account ADD COLUMN owner INTEGER NOT NULL DEFAULT 0`); err != nil { + log.Printf("error during database alert: %s", err) + } + if _, err := tx.Exec(`ALTER TABLE bookmark ADD COLUMN public INTEGER NOT NULL DEFAULT 0`); err != nil { + log.Printf("error during database alert: %s", err) + } err = tx.Commit() checkError(err) @@ -97,8 +103,9 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } result = []model.Bookmark{} err = panicErr } @@ -109,15 +116,15 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m (id, url, title, excerpt, author, public, modified) VALUES(?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET - url = ?, title = ?, excerpt = ?, author = ?, + url = ?, title = ?, excerpt = ?, author = ?, public = ?, modified = ?`) - stmtInsertBookContent, _ := tx.Preparex(`INSERT OR IGNORE INTO bookmark_content - (docid, title, content, html) - VALUES (?, ?, ?, ?)`) + // stmtInsertBookContent, _ := tx.Preparex(`INSERT OR IGNORE INTO bookmark_content + // (docid, title, content, html) + // VALUES (?, ?, ?, ?)`) stmtUpdateBookContent, _ := tx.Preparex(`UPDATE bookmark_content SET - title = ?, content = ?, html = ? + title = ?, content = ?, html = ? WHERE docid = ?`) stmtGetTag, _ := tx.Preparex(`SELECT id FROM tag WHERE name = ?`) @@ -158,7 +165,7 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m book.URL, book.Title, book.Excerpt, book.Author, book.Public, book.Modified) stmtUpdateBookContent.MustExec(book.Title, book.Content, book.HTML, book.ID) - stmtInsertBookContent.MustExec(book.ID, book.Title, book.Content, book.HTML) + //stmtInsertBookContent.MustExec(book.ID, book.Title, book.Content, book.HTML) // Save book tags newTags := []model.Tag{} @@ -187,7 +194,9 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m tag.ID = int(tagID64) } - stmtInsertBookTag.Exec(tag.ID, book.ID) + if _, err := stmtInsertBookTag.Exec(tag.ID, book.ID); err != nil { + log.Printf("error during insert: %s", err) + } } newTags = append(newTags, tag) @@ -215,7 +224,7 @@ func (db *SQLiteDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookma `b.author`, `b.public`, `b.modified`, - `bc.content <> "" has_content`,} + `bc.content <> "" has_content`} if opts.WithContent { columns = append(columns, `bc.content`, `bc.html`) @@ -238,8 +247,8 @@ func (db *SQLiteDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookma // Add where clause for search keyword if opts.Keyword != "" { query += ` AND (b.url LIKE ? OR b.excerpt LIKE ? OR b.id IN ( - SELECT docid id - FROM bookmark_content + SELECT docid id + FROM bookmark_content WHERE title MATCH ? OR content MATCH ?))` args = append(args, @@ -330,10 +339,10 @@ func (db *SQLiteDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookma } // Fetch tags for each bookmarks - stmtGetTags, err := db.Preparex(`SELECT t.id, t.name - FROM bookmark_tag bt + stmtGetTags, err := db.Preparex(`SELECT t.id, t.name + FROM bookmark_tag bt LEFT JOIN tag t ON bt.tag_id = t.id - WHERE bt.bookmark_id = ? + WHERE bt.bookmark_id = ? ORDER BY t.name`) if err != nil { return nil, fmt.Errorf("failed to prepare tag query: %v", err) @@ -373,8 +382,8 @@ func (db *SQLiteDatabase) GetBookmarksCount(opts GetBookmarksOptions) (int, erro // Add where clause for search keyword if opts.Keyword != "" { query += ` AND (b.url LIKE ? OR b.excerpt LIKE ? OR b.id IN ( - SELECT docid id - FROM bookmark_content + SELECT docid id + FROM bookmark_content WHERE title MATCH ? OR content MATCH ?))` args = append(args, @@ -464,8 +473,9 @@ func (db *SQLiteDatabase) DeleteBookmarks(ids ...int) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } }() @@ -520,7 +530,9 @@ func (db *SQLiteDatabase) GetBookmark(id int, url string) (model.Bookmark, bool) } book := model.Bookmark{} - db.Get(&book, query, args...) + if err := db.Get(&book, query, args...); err != nil { + log.Printf("error during db.get: %s", err) + } return book, book.ID != 0 } @@ -575,9 +587,12 @@ func (db *SQLiteDatabase) GetAccounts(opts GetAccountsOptions) ([]model.Account, // Returns the account and boolean whether it's exist or not. func (db *SQLiteDatabase) GetAccount(username string) (model.Account, bool) { account := model.Account{} - db.Get(&account, `SELECT + if err := db.Get(&account, `SELECT id, username, password, owner FROM account WHERE username = ?`, - username) + username, + ); err != nil { + log.Printf("error during db.get: %s", err) + } return account, account.ID != 0 } @@ -594,8 +609,9 @@ func (db *SQLiteDatabase) DeleteAccounts(usernames ...string) (err error) { defer func() { if r := recover(); r != nil { panicErr, _ := r.(error) - tx.Rollback() - + if err := tx.Rollback(); err != nil { + log.Printf("error during rollback: %s", err) + } err = panicErr } }() @@ -616,8 +632,8 @@ func (db *SQLiteDatabase) DeleteAccounts(usernames ...string) (err error) { // GetTags fetch list of tags and their frequency. func (db *SQLiteDatabase) GetTags() ([]model.Tag, error) { tags := []model.Tag{} - query := `SELECT bt.tag_id id, t.name, COUNT(bt.tag_id) n_bookmarks - FROM bookmark_tag bt + query := `SELECT bt.tag_id id, t.name, COUNT(bt.tag_id) n_bookmarks + FROM bookmark_tag bt LEFT JOIN tag t ON bt.tag_id = t.id GROUP BY bt.tag_id ORDER BY t.name` diff --git a/internal/webserver/handler-api.go b/internal/webserver/handler-api.go index bfc203181..f61d79610 100644 --- a/internal/webserver/handler-api.go +++ b/internal/webserver/handler-api.go @@ -103,8 +103,6 @@ func (h *handler) apiLogin(w http.ResponseWriter, r *http.Request, ps httprouter expTime := time.Hour if request.Remember { expTime = time.Hour * 24 * 30 - } else { - expTime = time.Hour } // Create session @@ -675,7 +673,7 @@ func (h *handler) apiDeleteAccount(w http.ResponseWriter, r *http.Request, ps ht checkError(err) // Delete user's sessions - userSessions := []string{} + var userSessions []string for _, username := range usernames { if val, found := h.UserCache.Get(username); found { userSessions = val.([]string) diff --git a/internal/webserver/handler-ui.go b/internal/webserver/handler-ui.go index d398fee8e..428d9f1b4 100644 --- a/internal/webserver/handler-ui.go +++ b/internal/webserver/handler-ui.go @@ -5,6 +5,7 @@ import ( "compress/gzip" "fmt" "io" + "log" "net/http" "os" "path" @@ -58,7 +59,9 @@ func (h *handler) serveIndexPage(w http.ResponseWriter, r *http.Request, ps http } if developmentMode { - h.prepareTemplates() + if err := h.prepareTemplates(); err != nil { + log.Printf("error during template preparation: %s", err) + } } err = h.templates["index"].Execute(w, h.RootPath) @@ -76,7 +79,9 @@ func (h *handler) serveLoginPage(w http.ResponseWriter, r *http.Request, ps http } if developmentMode { - h.prepareTemplates() + if err := h.prepareTemplates(); err != nil { + log.Printf("error during template preparation: %s", err) + } } err = h.templates["login"].Execute(w, h.RootPath) @@ -177,7 +182,9 @@ func (h *handler) serveBookmarkContent(w http.ResponseWriter, r *http.Request, p // Execute template if developmentMode { - h.prepareTemplates() + if err := h.prepareTemplates(); err != nil { + log.Printf("error during template preparation: %s", err) + } } tplData := struct { @@ -217,7 +224,9 @@ func (h *handler) serveThumbnailImage(w http.ResponseWriter, r *http.Request, ps w.Header().Set("Cache-Control", "max-age=86400") // Serve image - img.Seek(0, 0) + if _, err := img.Seek(0, 0); err != nil { + log.Printf("error during image seek: %s", err) + } _, err = io.Copy(w, img) checkError(err) } @@ -301,11 +310,15 @@ func (h *handler) serveBookmarkArchive(w http.ResponseWriter, r *http.Request, p // Gzip it again and send to response writer gzipWriter := gzip.NewWriter(w) - gzipWriter.Write([]byte(outerHTML)) + if _, err := gzipWriter.Write([]byte(outerHTML)); err != nil { + log.Printf("error writting gzip file: %s", err) + } gzipWriter.Flush() return } // Serve content - w.Write(content) + if _, err := w.Write(content); err != nil { + log.Printf("error writting response: %s", err) + } }