shiori/internal/cmd/root.go

144 lines
3.2 KiB
Go

package cmd
import (
"fmt"
"log"
"os"
fp "path/filepath"
"github.com/go-shiori/shiori/internal/database"
apppaths "github.com/muesli/go-app-paths"
"github.com/spf13/cobra"
)
var (
db database.DB
dataDir string
developmentMode bool
)
// ShioriCmd returns the root command for shiori
func ShioriCmd() *cobra.Command {
rootCmd := &cobra.Command{
Use: "shiori",
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(),
updateCmd(),
deleteCmd(),
openCmd(),
importCmd(),
exportCmd(),
pocketCmd(),
serveCmd(),
checkCmd(),
)
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)
}
log.Println(dataDir)
err = os.MkdirAll(dataDir, os.ModePerm)
if err != nil {
cError.Printf("Failed to create data dir: %v\n", err)
os.Exit(1)
}
// Open database
db, err = openDatabase()
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")
dataDir, err := userScope.DataPath("shiori")
if err == nil {
return dataDir, nil
}
// TODO: Log warn
// When all fail, use current working directory
return ".", nil
}
func openDatabase() (database.DB, error) {
switch dbms, _ := os.LookupEnv("SHIORI_DBMS"); dbms {
case "mysql":
return openMySQLDatabase()
case "postgresql":
return openPostgreSQLDatabase()
default:
return openSQLiteDatabase()
}
}
func openSQLiteDatabase() (database.DB, error) {
dbPath := fp.Join(dataDir, "shiori.db")
return database.OpenSQLiteDatabase(dbPath)
}
func openMySQLDatabase() (database.DB, error) {
user, _ := os.LookupEnv("SHIORI_MYSQL_USER")
password, _ := os.LookupEnv("SHIORI_MYSQL_PASS")
dbName, _ := os.LookupEnv("SHIORI_MYSQL_NAME")
dbAddress, _ := os.LookupEnv("SHIORI_MYSQL_ADDRESS")
connString := fmt.Sprintf("%s:%s@%s/%s?charset=utf8mb4", user, password, dbAddress, dbName)
return database.OpenMySQLDatabase(connString)
}
func openPostgreSQLDatabase() (database.DB, error) {
host, _ := os.LookupEnv("SHIORI_PG_HOST")
port, _ := os.LookupEnv("SHIORI_PG_PORT")
user, _ := os.LookupEnv("SHIORI_PG_USER")
password, _ := os.LookupEnv("SHIORI_PG_PASS")
dbName, _ := os.LookupEnv("SHIORI_PG_NAME")
connString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
host, port, user, password, dbName)
return database.OpenPGDatabase(connString)
}