mirror of
https://github.com/go-shiori/shiori.git
synced 2025-01-27 10:19:29 +08:00
Restructure project directories
This commit is contained in:
parent
1b75fc1ead
commit
1e099fbd27
23 changed files with 375 additions and 2 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
|||
# Exclude config file
|
||||
.vscode/
|
||||
*.toml
|
||||
*.toml
|
||||
|
||||
# Exclude executable file
|
||||
/shiori*
|
2
go.mod
2
go.mod
|
@ -3,6 +3,8 @@ module github.com/go-shiori/shiori
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/cobra v0.0.4
|
||||
google.golang.org/appengine v1.6.0 // indirect
|
||||
)
|
||||
|
|
12
go.sum
12
go.sum
|
@ -7,12 +7,21 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
@ -35,9 +44,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw=
|
||||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
13
internal/cmd/account-add.go
Normal file
13
internal/cmd/account-add.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func accountAddCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add username",
|
||||
Short: "Create new account",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
17
internal/cmd/account-delete.go
Normal file
17
internal/cmd/account-delete.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func accountDeleteCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete [usernames]",
|
||||
Short: "Delete the saved accounts",
|
||||
Long: "Delete accounts. " +
|
||||
"Accepts space-separated list of usernames. " +
|
||||
"If no arguments, all records will be deleted.",
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and delete ALL accounts")
|
||||
|
||||
return cmd
|
||||
}
|
16
internal/cmd/account-print.go
Normal file
16
internal/cmd/account-print.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func accountPrintCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "print",
|
||||
Short: "Print the saved accounts",
|
||||
Args: cobra.NoArgs,
|
||||
Aliases: []string{"list", "ls"},
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("search", "s", "", "Search accounts by username")
|
||||
|
||||
return cmd
|
||||
}
|
20
internal/cmd/account.go
Normal file
20
internal/cmd/account.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func accountCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "account",
|
||||
Short: "Manage account for accessing web interface",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
accountAddCmd(),
|
||||
accountPrintCmd(),
|
||||
accountDeleteCmd(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
20
internal/cmd/add.go
Normal file
20
internal/cmd/add.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func addCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add url",
|
||||
Short: "Bookmark the specified URL",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("title", "i", "", "Custom title for this bookmark.")
|
||||
cmd.Flags().StringP("excerpt", "e", "", "Custom excerpt for this bookmark.")
|
||||
cmd.Flags().StringSliceP("tags", "t", []string{}, "Comma-separated tags for this bookmark.")
|
||||
cmd.Flags().BoolP("offline", "o", false, "Save bookmark without fetching data from internet.")
|
||||
|
||||
return cmd
|
||||
}
|
21
internal/cmd/delete.go
Normal file
21
internal/cmd/delete.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func deleteCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete [indices]",
|
||||
Short: "Delete the saved bookmarks",
|
||||
Long: "Delete bookmarks. " +
|
||||
"When a record is deleted, the last record is moved to the removed 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 will be deleted.",
|
||||
Aliases: []string{"rm"},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and delete ALL bookmarks")
|
||||
|
||||
return cmd
|
||||
}
|
15
internal/cmd/export.go
Normal file
15
internal/cmd/export.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func exportCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "export target-file",
|
||||
Short: "Export bookmarks into HTML file in Netscape Bookmark format",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
15
internal/cmd/import.go
Normal file
15
internal/cmd/import.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func importCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "import source-file",
|
||||
Short: "Import bookmarks from HTML file in Netscape Bookmark format",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("generate-tag", "t", false, "Auto generate tag from bookmark's category")
|
||||
|
||||
return cmd
|
||||
}
|
22
internal/cmd/open.go
Normal file
22
internal/cmd/open.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func openCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "open [indices]",
|
||||
Short: "Open the saved bookmarks",
|
||||
Long: "Open bookmarks in browser. " +
|
||||
"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 opened.",
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and open ALL bookmarks")
|
||||
cmd.Flags().BoolP("cache", "c", false, "Open the bookmark's cache in text-only mode")
|
||||
cmd.Flags().Bool("trim-space", false, "Trim all spaces and newlines from the bookmark's cache")
|
||||
|
||||
return cmd
|
||||
}
|
15
internal/cmd/pocket.go
Normal file
15
internal/cmd/pocket.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func pocketCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "pocket source-file",
|
||||
Short: "Import bookmarks from Pocket's exported HTML file",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
20
internal/cmd/print.go
Normal file
20
internal/cmd/print.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func printCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "print [indices]",
|
||||
Short: "Print the saved bookmarks",
|
||||
Long: "Show the saved bookmarks by its DB 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.",
|
||||
Aliases: []string{"list", "ls"},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("json", "j", false, "Output data in JSON format")
|
||||
cmd.Flags().BoolP("index-only", "i", false, "Only print the index of bookmarks")
|
||||
|
||||
return cmd
|
||||
}
|
29
internal/cmd/root.go
Normal file
29
internal/cmd/root.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// 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.AddCommand(
|
||||
accountCmd(),
|
||||
addCmd(),
|
||||
printCmd(),
|
||||
searchCmd(),
|
||||
updateCmd(),
|
||||
deleteCmd(),
|
||||
openCmd(),
|
||||
importCmd(),
|
||||
exportCmd(),
|
||||
pocketCmd(),
|
||||
serveCmd(),
|
||||
)
|
||||
|
||||
return rootCmd
|
||||
}
|
22
internal/cmd/search.go
Normal file
22
internal/cmd/search.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func searchCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "search keyword",
|
||||
Short: "Search bookmarks by submitted keyword",
|
||||
Long: "Search bookmarks by looking for matching keyword in bookmark's title and content. " +
|
||||
"If no keyword submitted, print all saved bookmarks. " +
|
||||
"Search results will be different depending on DBMS that used by shiori :\n" +
|
||||
"- sqlite3, search works using fts4 method: https://www.sqlite.org/fts3.html.\n" +
|
||||
"- mysql or mariadb, search works using natural language mode: https://dev.mysql.com/doc/refman/5.5/en/fulltext-natural-language.html.",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("json", "j", false, "Output data in JSON format")
|
||||
cmd.Flags().BoolP("index-only", "i", false, "Only print the index of bookmarks")
|
||||
cmd.Flags().StringSliceP("tags", "t", []string{}, "Search bookmarks with specified tag(s)")
|
||||
|
||||
return cmd
|
||||
}
|
19
internal/cmd/serve.go
Normal file
19
internal/cmd/serve.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func serveCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "Serve web interface for managing bookmarks",
|
||||
Long: "Run a simple annd performant web server which " +
|
||||
"serves the site for managing bookmarks. If --port " +
|
||||
"flag is not used, it will use port 8080 by default.",
|
||||
}
|
||||
|
||||
cmd.Flags().IntP("port", "p", 8080, "Port that used by server")
|
||||
|
||||
return cmd
|
||||
}
|
27
internal/cmd/update.go
Normal file
27
internal/cmd/update.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func updateCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "update [indices]",
|
||||
Short: "Update the saved bookmarks",
|
||||
Long: "Update fields of an existing bookmark. " +
|
||||
"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 --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).",
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("url", "u", "", "New URL for this bookmark.")
|
||||
cmd.Flags().StringP("title", "i", "", "New title for this bookmark.")
|
||||
cmd.Flags().StringP("excerpt", "e", "", "New excerpt for this bookmark.")
|
||||
cmd.Flags().StringSliceP("tags", "t", []string{}, "Comma-separated tags for this bookmark.")
|
||||
cmd.Flags().BoolP("offline", "o", false, "Update bookmark without fetching data from internet.")
|
||||
cmd.Flags().BoolP("yes", "y", false, "Skip confirmation prompt and update ALL bookmarks")
|
||||
cmd.Flags().Bool("dont-overwrite", false, "Don't overwrite existing metadata. Useful when only want to update bookmark's content.")
|
||||
|
||||
return cmd
|
||||
}
|
5
internal/database/database.go
Normal file
5
internal/database/database.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package database
|
||||
|
||||
// DB is interface for accessing and manipulating data in database.
|
||||
type DB interface {
|
||||
}
|
11
internal/database/sqlite.go
Normal file
11
internal/database/sqlite.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
// SQLiteDatabase is implementation of Database interface
|
||||
// for connecting to SQLite3 database.
|
||||
type SQLiteDatabase struct {
|
||||
sqlx.DB
|
||||
}
|
40
internal/model/model.go
Normal file
40
internal/model/model.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package model
|
||||
|
||||
// Tag is the tag for a bookmark.
|
||||
type Tag struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
NBookmarks int `db:"n_bookmarks" json:"nBookmarks"`
|
||||
Deleted bool `json:"-"`
|
||||
}
|
||||
|
||||
// Bookmark is the record for an URL.
|
||||
type Bookmark struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
URL string `db:"url" json:"url"`
|
||||
Title string `db:"title" json:"title"`
|
||||
ImageURL string `db:"image_url" json:"imageURL"`
|
||||
Excerpt string `db:"excerpt" json:"excerpt"`
|
||||
Author string `db:"author" json:"author"`
|
||||
MinReadTime int `db:"min_read_time" json:"minReadTime"`
|
||||
MaxReadTime int `db:"max_read_time" json:"maxReadTime"`
|
||||
Modified string `db:"modified" json:"modified"`
|
||||
Content string `db:"content" json:"-"`
|
||||
HTML string `db:"html" json:"html,omitempty"`
|
||||
HasContent bool `db:"has_content" json:"hasContent"`
|
||||
Tags []Tag `json:"tags"`
|
||||
}
|
||||
|
||||
// Account is person that allowed to access web interface.
|
||||
type Account struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Username string `db:"username" json:"username"`
|
||||
Password string `db:"password" json:"password"`
|
||||
}
|
||||
|
||||
// LoginRequest is request from user to access web interface.
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Remember bool `json:"remember"`
|
||||
}
|
1
internal/webserver/server.go
Normal file
1
internal/webserver/server.go
Normal file
|
@ -0,0 +1 @@
|
|||
package webserver
|
10
main.go
10
main.go
|
@ -1,5 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-shiori/shiori/internal/cmd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//
|
||||
shioriCmd := cmd.ShioriCmd()
|
||||
if err := shioriCmd.Execute(); err != nil {
|
||||
logrus.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue