diff --git a/.gitignore b/.gitignore index b9e5997..48bb5d9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ tmp/ *.db *.bin dist/ +config.toml diff --git a/README.md b/README.md index b021cf7..9975bfa 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,8 @@ LinkPage is a FOSS self-hosted alternative to link listing websites such as Link 1. Download the latest release 2. Decompress the archive -3. Create a sqlite db with the schema using `sqlite3 linkpage.db < schema.sql` -4. Copy the [config file](config.toml) and update it with your settings -5. Run the app using `./linkpage` +3. Run the app using `./linkpage --init`, this will generate an empty sqlite database and config file in your local directory. +4. Now you can run the app using `./linkpage`, goto the `/admin` page to add new entries. ## Developer Setup diff --git a/config.toml b/config.sample.toml similarity index 100% rename from config.toml rename to config.sample.toml diff --git a/main.go b/main.go index cd7f727..91c788f 100644 --- a/main.go +++ b/main.go @@ -5,8 +5,10 @@ import ( "embed" "fmt" "io" + "io/ioutil" "log" "net/http" + "os" "strconv" "sync" "text/template" @@ -19,6 +21,7 @@ import ( "github.com/knadh/koanf/providers/file" _ "github.com/mattn/go-sqlite3" "github.com/otiai10/opengraph/v2" + flag "github.com/spf13/pflag" "github.com/urfave/negroni" ) @@ -28,6 +31,9 @@ var templateFS embed.FS //go:embed static var staticFS embed.FS +//go:embed schema.sql config.sample.toml +var setupFS embed.FS + type Config struct { HTTPAddr string `koanf:"http_address"` ReadTimeout time.Duration `koanf:"read_timeout"` @@ -253,8 +259,24 @@ func basicAuth(cfg Config) negroni.HandlerFunc { }) } -func main() { - cfg := initConfig("config.toml") +var ( + appMode = "run_app" + configFilePath = "config.toml" +) + +func init() { + flag.StringVar(&configFilePath, "config", "config.toml", "path to config file") + initApp := flag.Bool("init", false, "app initialization, creates a db and config file in current dir") + + flag.Parse() + + if *initApp == true { + appMode = "init_app" + } +} + +func runApp(configFilePath string) { + cfg := initConfig(configFilePath) db, err := sqlx.Connect("sqlite3", cfg.DBFile) if err != nil { @@ -536,3 +558,68 @@ func main() { log.Println("starting server at", cfg.HTTPAddr) log.Fatal(srv.ListenAndServe()) } + +func initApp() { + file, err := os.Create("app.db") + if err != nil { + log.Fatal(err) + } + file.Close() + + db, err := sqlx.Connect("sqlite3", "app.db") + if err != nil { + log.Fatal(err) + } + + schemaFile, err := setupFS.Open("schema.sql") + if err != nil { + log.Fatal(err) + } + + schema, err := ioutil.ReadAll(schemaFile) + if err != nil { + log.Fatal(err) + } + + if err := schemaFile.Close(); err != nil { + log.Fatal(err) + } + + if _, err := db.Exec(string(schema)); err != nil { + log.Fatal(err) + } + + if err := db.Close(); err != nil { + log.Fatal(err) + } + + outCfgFile, err := os.Create("config.toml") + if err != nil { + log.Fatal(err) + } + defer outCfgFile.Close() + + setupCfgFile, err := setupFS.Open("config.sample.toml") + if err != nil { + log.Fatal(err) + } + defer setupCfgFile.Close() + + if _, err := io.Copy(outCfgFile, setupCfgFile); err != nil { + log.Fatal(err) + } + + log.Println("config.toml and app.db generated.") +} + +func main() { + log.Println(appMode) + switch appMode { + case "init_app": + initApp() + case "run_app": + runApp(configFilePath) + default: + runApp(configFilePath) + } +}