mirror of
https://github.com/go-shiori/shiori.git
synced 2025-01-15 04:17:43 +08:00
Add portable mode
This commit is contained in:
parent
20e89216f0
commit
ad502c6749
13 changed files with 106 additions and 86 deletions
|
@ -63,7 +63,7 @@ func addHandler(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// Create bookmark ID
|
||||
book.ID, err = DB.CreateNewID("bookmark")
|
||||
book.ID, err = db.CreateNewID("bookmark")
|
||||
if err != nil {
|
||||
cError.Printf("Failed to create ID: %v\n", err)
|
||||
return
|
||||
|
@ -150,7 +150,7 @@ func addHandler(cmd *cobra.Command, args []string) {
|
|||
|
||||
// If needed, create offline archive as well
|
||||
if !noArchival {
|
||||
archivePath := fp.Join(DataDir, "archive", fmt.Sprintf("%d", book.ID))
|
||||
archivePath := fp.Join(dataDir, "archive", fmt.Sprintf("%d", book.ID))
|
||||
archivalRequest := warc.ArchivalRequest{
|
||||
URL: url,
|
||||
Reader: archivalInput,
|
||||
|
@ -173,14 +173,14 @@ func addHandler(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// Save bookmark to database
|
||||
_, err = DB.SaveBookmarks(book)
|
||||
_, err = db.SaveBookmarks(book)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to save bookmark: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Save article image to local disk
|
||||
imgPath := fp.Join(DataDir, "thumb", fmt.Sprintf("%d", book.ID))
|
||||
imgPath := fp.Join(dataDir, "thumb", fmt.Sprintf("%d", book.ID))
|
||||
for _, imageURL := range imageURLs {
|
||||
err = downloadBookImage(imageURL, imgPath, time.Minute)
|
||||
if err == nil {
|
||||
|
|
|
@ -52,7 +52,7 @@ func deleteHandler(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// Delete bookmarks from database
|
||||
err = DB.DeleteBookmarks(ids...)
|
||||
err = db.DeleteBookmarks(ids...)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to delete bookmarks: %v\n", err)
|
||||
return
|
||||
|
@ -60,15 +60,15 @@ func deleteHandler(cmd *cobra.Command, args []string) {
|
|||
|
||||
// Delete thumbnail image and archives from local disk
|
||||
if len(ids) == 0 {
|
||||
thumbDir := fp.Join(DataDir, "thumb")
|
||||
archiveDir := fp.Join(DataDir, "archive")
|
||||
thumbDir := fp.Join(dataDir, "thumb")
|
||||
archiveDir := fp.Join(dataDir, "archive")
|
||||
os.RemoveAll(thumbDir)
|
||||
os.RemoveAll(archiveDir)
|
||||
} else {
|
||||
for _, id := range ids {
|
||||
strID := strconv.Itoa(id)
|
||||
imgPath := fp.Join(DataDir, "thumb", strID)
|
||||
archivePath := fp.Join(DataDir, "archive", strID)
|
||||
imgPath := fp.Join(dataDir, "thumb", strID)
|
||||
archivePath := fp.Join(dataDir, "archive", strID)
|
||||
|
||||
os.Remove(imgPath)
|
||||
os.Remove(archivePath)
|
||||
|
|
|
@ -25,7 +25,7 @@ func exportCmd() *cobra.Command {
|
|||
|
||||
func exportHandler(cmd *cobra.Command, args []string) {
|
||||
// Fetch bookmarks from database
|
||||
bookmarks, err := DB.GetBookmarks(database.GetBookmarksOptions{})
|
||||
bookmarks, err := db.GetBookmarks(database.GetBookmarksOptions{})
|
||||
if err != nil {
|
||||
cError.Printf("Failed to get bookmarks: %v\n", err)
|
||||
return
|
||||
|
|
|
@ -40,7 +40,7 @@ func importHandler(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// Prepare bookmark's ID
|
||||
bookID, err := DB.CreateNewID("bookmark")
|
||||
bookID, err := db.CreateNewID("bookmark")
|
||||
if err != nil {
|
||||
cError.Printf("Failed to create ID: %v\n", err)
|
||||
return
|
||||
|
@ -96,7 +96,7 @@ func importHandler(cmd *cobra.Command, args []string) {
|
|||
return
|
||||
}
|
||||
|
||||
if _, exist := DB.GetBookmark(0, url); exist {
|
||||
if _, exist := db.GetBookmark(0, url); exist {
|
||||
cError.Printf("Skip %s: URL already exists\n", url)
|
||||
mapURL[url] = struct{}{}
|
||||
return
|
||||
|
@ -133,7 +133,7 @@ func importHandler(cmd *cobra.Command, args []string) {
|
|||
})
|
||||
|
||||
// Save bookmark to database
|
||||
bookmarks, err = DB.SaveBookmarks(bookmarks...)
|
||||
bookmarks, err = db.SaveBookmarks(bookmarks...)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to save bookmarks: %v\n", err)
|
||||
return
|
||||
|
|
|
@ -72,7 +72,7 @@ func openHandler(cmd *cobra.Command, args []string) {
|
|||
WithContent: true,
|
||||
}
|
||||
|
||||
bookmarks, err := DB.GetBookmarks(getOptions)
|
||||
bookmarks, err := db.GetBookmarks(getOptions)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to get bookmarks: %v\n", err)
|
||||
return
|
||||
|
@ -123,7 +123,7 @@ func openHandler(cmd *cobra.Command, args []string) {
|
|||
|
||||
// Open archive
|
||||
id := strconv.Itoa(bookmarks[0].ID)
|
||||
archivePath := fp.Join(DataDir, "archive", id)
|
||||
archivePath := fp.Join(dataDir, "archive", id)
|
||||
|
||||
archive, err := warc.Open(archivePath)
|
||||
if err != nil {
|
||||
|
|
|
@ -26,7 +26,7 @@ func pocketCmd() *cobra.Command {
|
|||
|
||||
func pocketHandler(cmd *cobra.Command, args []string) {
|
||||
// Prepare bookmark's ID
|
||||
bookID, err := DB.CreateNewID("bookmark")
|
||||
bookID, err := db.CreateNewID("bookmark")
|
||||
if err != nil {
|
||||
cError.Printf("Failed to create ID: %v\n", err)
|
||||
return
|
||||
|
@ -77,7 +77,7 @@ func pocketHandler(cmd *cobra.Command, args []string) {
|
|||
return
|
||||
}
|
||||
|
||||
if _, exist := DB.GetBookmark(0, url); exist {
|
||||
if _, exist := db.GetBookmark(0, url); exist {
|
||||
cError.Printf("Skip %s: URL already exists\n", url)
|
||||
mapURL[url] = struct{}{}
|
||||
return
|
||||
|
@ -106,7 +106,7 @@ func pocketHandler(cmd *cobra.Command, args []string) {
|
|||
})
|
||||
|
||||
// Save bookmark to database
|
||||
bookmarks, err = DB.SaveBookmarks(bookmarks...)
|
||||
bookmarks, err = db.SaveBookmarks(bookmarks...)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to save bookmarks: %v\n", err)
|
||||
return
|
||||
|
|
|
@ -12,7 +12,7 @@ func printCmd() *cobra.Command {
|
|||
cmd := &cobra.Command{
|
||||
Use: "print [indices]",
|
||||
Short: "Print the saved bookmarks",
|
||||
Long: "Show the saved bookmarks by its DB index. " +
|
||||
Long: "Show the saved bookmarks by its database index. " +
|
||||
"Accepts space-separated list of indices (e.g. 5 6 23 4 110 45), " +
|
||||
"hyphenated range (e.g. 100-200) or both (e.g. 1-3 7 9). " +
|
||||
"If no arguments, all records with actual index from database are shown.",
|
||||
|
@ -57,7 +57,7 @@ func printHandler(cmd *cobra.Command, args []string) {
|
|||
OrderMethod: orderMethod,
|
||||
}
|
||||
|
||||
bookmarks, err := DB.GetBookmarks(searchOptions)
|
||||
bookmarks, err := db.GetBookmarks(searchOptions)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to get bookmarks: %v\n", err)
|
||||
return
|
||||
|
|
7
internal/cmd/root-dev.go
Normal file
7
internal/cmd/root-dev.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
// +build dev
|
||||
|
||||
package cmd
|
||||
|
||||
func init() {
|
||||
developmentMode = true
|
||||
}
|
|
@ -4,20 +4,20 @@ import (
|
|||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"os"
|
||||
fp "path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/go-shiori/shiori/internal/database"
|
||||
apppaths "github.com/muesli/go-app-paths"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
// DB is database that used by cmd
|
||||
DB database.DB
|
||||
|
||||
// DataDir is directory for downloaded data
|
||||
DataDir string
|
||||
|
||||
httpClient *http.Client
|
||||
db database.DB
|
||||
dataDir string
|
||||
httpClient *http.Client
|
||||
developmentMode bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -40,6 +40,8 @@ func ShioriCmd() *cobra.Command {
|
|||
Short: "Simple command-line bookmark manager built with Go",
|
||||
}
|
||||
|
||||
rootCmd.PersistentPreRun = preRunRootHandler
|
||||
rootCmd.PersistentFlags().Bool("portable", false, "run shiori in portable mode")
|
||||
rootCmd.AddCommand(
|
||||
addCmd(),
|
||||
printCmd(),
|
||||
|
@ -54,3 +56,63 @@ func ShioriCmd() *cobra.Command {
|
|||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func preRunRootHandler(cmd *cobra.Command, args []string) {
|
||||
// Read flag
|
||||
var err error
|
||||
portableMode, _ := cmd.Flags().GetBool("portable")
|
||||
|
||||
// Get and create data dir
|
||||
dataDir, err = getDataDir(portableMode)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to get data dir: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dataDir, os.ModePerm)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to create data dir: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Open database
|
||||
dbPath := fp.Join(dataDir, "shiori.db")
|
||||
db, err = database.OpenSQLiteDatabase(dbPath)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to open database: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func getDataDir(portableMode bool) (string, error) {
|
||||
// If in portable mode, uses directory of executable
|
||||
if portableMode {
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
exeDir := fp.Dir(exePath)
|
||||
return fp.Join(exeDir, "shiori-data"), nil
|
||||
}
|
||||
|
||||
if developmentMode {
|
||||
return "dev-data", nil
|
||||
}
|
||||
|
||||
// Try to look at environment variables
|
||||
dataDir, found := os.LookupEnv("SHIORI_DIR")
|
||||
if found {
|
||||
return dataDir, nil
|
||||
}
|
||||
|
||||
// Try to use platform specific app path
|
||||
userScope := apppaths.NewScope(apppaths.User, "shiori", "shiori")
|
||||
dataDir, err := userScope.DataDir()
|
||||
if err == nil {
|
||||
return dataDir, nil
|
||||
}
|
||||
|
||||
// When all fail, use current working directory
|
||||
return ".", nil
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func serveCmd() *cobra.Command {
|
|||
func serveHandler(cmd *cobra.Command, args []string) {
|
||||
port, _ := cmd.Flags().GetInt("port")
|
||||
|
||||
err := webserver.ServeApp(DB, DataDir, port)
|
||||
err := webserver.ServeApp(db, dataDir, port)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Server error: %v\n", err)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func updateCmd() *cobra.Command {
|
|||
"Accepts space-separated list of indices (e.g. 5 6 23 4 110 45), " +
|
||||
"hyphenated range (e.g. 100-200) or both (e.g. 1-3 7 9). " +
|
||||
"If no arguments, ALL bookmarks will be updated. Update works differently depending on the flags:\n" +
|
||||
"- If indices are passed without any flags (--url, --title, --tag and --excerpt), read the URLs from DB and update titles from web.\n" +
|
||||
"- If indices are passed without any flags (--url, --title, --tag and --excerpt), read the URLs from database and update titles from web.\n" +
|
||||
"- If --url is passed (and --title is omitted), update the title from web using the URL. While using this flag, update only accept EXACTLY one index.\n" +
|
||||
"While updating bookmark's tags, you can use - to remove tag (e.g. -nature to remove nature tag from this bookmark).",
|
||||
Run: updateHandler,
|
||||
|
@ -106,7 +106,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
|
|||
IDs: ids,
|
||||
}
|
||||
|
||||
bookmarks, err := DB.GetBookmarks(filterOptions)
|
||||
bookmarks, err := db.GetBookmarks(filterOptions)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to get bookmarks: %v\n", err)
|
||||
return
|
||||
|
@ -230,7 +230,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
|
|||
imageURLs = append(imageURLs, article.Favicon)
|
||||
}
|
||||
|
||||
imgPath := fp.Join(DataDir, "thumb", fmt.Sprintf("%d", book.ID))
|
||||
imgPath := fp.Join(dataDir, "thumb", fmt.Sprintf("%d", book.ID))
|
||||
for _, imageURL := range imageURLs {
|
||||
err = downloadBookImage(imageURL, imgPath, time.Minute)
|
||||
if err == nil {
|
||||
|
@ -242,7 +242,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
|
|||
// If needed, update offline archive as well.
|
||||
// Make sure to delete the old one first.
|
||||
if !noArchival {
|
||||
archivePath := fp.Join(DataDir, "archive", fmt.Sprintf("%d", book.ID))
|
||||
archivePath := fp.Join(dataDir, "archive", fmt.Sprintf("%d", book.ID))
|
||||
os.Remove(archivePath)
|
||||
|
||||
archivalRequest := warc.ArchivalRequest{
|
||||
|
@ -360,7 +360,7 @@ func updateHandler(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
// Save bookmarks to database
|
||||
bookmarks, err = DB.SaveBookmarks(bookmarks...)
|
||||
bookmarks, err = db.SaveBookmarks(bookmarks...)
|
||||
if err != nil {
|
||||
cError.Printf("Failed to save bookmark: %v\n", err)
|
||||
return
|
||||
|
|
22
main.go
22
main.go
|
@ -3,14 +3,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
fp "path/filepath"
|
||||
|
||||
"github.com/go-shiori/shiori/internal/cmd"
|
||||
"github.com/go-shiori/shiori/internal/database"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
// Database driver
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
||||
// Add this to prevent it removed by go mod tidy
|
||||
_ "github.com/shurcooL/vfsgen"
|
||||
)
|
||||
|
@ -18,20 +16,8 @@ import (
|
|||
var dataDir = "dev-data"
|
||||
|
||||
func main() {
|
||||
// Make sure data dir exists
|
||||
os.MkdirAll(dataDir, os.ModePerm)
|
||||
|
||||
// Open database
|
||||
dbPath := fp.Join(dataDir, "shiori.db")
|
||||
sqliteDB, err := database.OpenSQLiteDatabase(dbPath)
|
||||
err := cmd.ShioriCmd().Execute()
|
||||
if err != nil {
|
||||
logrus.Fatalln(err)
|
||||
}
|
||||
|
||||
// Execute cmd
|
||||
cmd.DB = sqliteDB
|
||||
cmd.DataDir = dataDir
|
||||
if err := cmd.ShioriCmd().Execute(); err != nil {
|
||||
logrus.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// +build !dev
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
apppaths "github.com/muesli/go-app-paths"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Get data directory
|
||||
dataDir = getDataDirectory()
|
||||
|
||||
// Make sure directory exist
|
||||
os.MkdirAll(dataDir, os.ModePerm)
|
||||
}
|
||||
|
||||
func getDataDirectory() string {
|
||||
// Try to look at environment variables
|
||||
dataDir, found := os.LookupEnv("SHIORI_DIR")
|
||||
if found {
|
||||
return dataDir
|
||||
}
|
||||
|
||||
// Try to use platform specific app path
|
||||
userScope := apppaths.NewScope(apppaths.User, "shiori", "shiori")
|
||||
dataDir, err := userScope.DataDir()
|
||||
if err == nil {
|
||||
return dataDir
|
||||
}
|
||||
|
||||
// When all fail, use current working directory
|
||||
return "."
|
||||
}
|
Loading…
Reference in a new issue