diff --git a/ana.go b/ana.go index a05ce91..c2618b2 100644 --- a/ana.go +++ b/ana.go @@ -1,16 +1,30 @@ package main import ( - "log" - "github.com/dannyvankooten/ana/commands" "github.com/dannyvankooten/ana/count" "github.com/dannyvankooten/ana/db" "github.com/joho/godotenv" "github.com/robfig/cron" + "gopkg.in/alecthomas/kingpin.v2" + "log" + "os" +) + +var ( + app = kingpin.New("ana", "Open-source web analytics.") + register = app.Command("register", "Register a new user.") + registerEmail = register.Arg("email", "Email for user.").Required().String() + registerPassword = register.Arg("password", "Password for user.").Required().String() + server = app.Command("server", "Start webserver.").Default() + serverPort = server.Flag("port", "Port to listen on.").Default("8080").Int() + archive = app.Command("archive", "Process unarchived data.") + seed = app.Command("seed", "Seed the database.") + seedN = seed.Flag("n", "Number of records to seed.").Int() ) func main() { + // load .env file err := godotenv.Load() if err != nil { @@ -30,6 +44,20 @@ func main() { c.Start() // parse & run cli commands - commands.Parse() - commands.Run() + app.Version("1.0") + app.UsageTemplate(kingpin.CompactUsageTemplate) + switch kingpin.MustParse(app.Parse(os.Args[1:])) { + case "register": + commands.Register(*registerEmail, *registerPassword) + + case "server": + commands.Server(*serverPort) + + case "archive": + commands.Archive() + + case "seed": + commands.Seed(*seedN) + } + } diff --git a/commands/commands.go b/commands/commands.go deleted file mode 100644 index 4b69690..0000000 --- a/commands/commands.go +++ /dev/null @@ -1,52 +0,0 @@ -package commands - -import ( - "flag" - - "github.com/dannyvankooten/ana/count" - "github.com/dannyvankooten/ana/db" -) - -var ( - runCreateUserCommand bool - runDeleteUserCommand bool - runStartServerCommand bool - runSeedDataCommand bool - runArchiveDataCommand bool - idArg int - emailArg string - passwordArg string - nArg int - portArg int -) - -// Parse CLI arguments -func Parse() { - // parse commands - flag.BoolVar(&runCreateUserCommand, "create_user", false, "Create a new user") - flag.BoolVar(&runDeleteUserCommand, "delete_user", false, "Deletes a user") - flag.BoolVar(&runStartServerCommand, "start_server", true, "Start the API web server, listen on -port") - flag.BoolVar(&runSeedDataCommand, "db_seed", false, "Seed the database -n times") - flag.BoolVar(&runArchiveDataCommand, "archive_data", false, "Aggregates data into daily totals") - flag.StringVar(&emailArg, "email", "", "Email address") - flag.StringVar(&passwordArg, "password", "", "Password") - flag.IntVar(&idArg, "id", 0, "Object ID") - flag.IntVar(&nArg, "n", 0, "Number") - flag.IntVar(&portArg, "port", 8080, "Port") - flag.Parse() -} - -// Run parsed CLI command. Defaults to starting the HTTP server. -func Run() { - if runCreateUserCommand { - createUser() - } else if runDeleteUserCommand { - deleteUser() - } else if runSeedDataCommand { - db.Seed(nArg) - } else if runArchiveDataCommand { - count.Archive() - } else if runStartServerCommand { - startServer(portArg) - } -} diff --git a/commands/data.go b/commands/data.go new file mode 100644 index 0000000..8fcca79 --- /dev/null +++ b/commands/data.go @@ -0,0 +1,16 @@ +package commands + +import ( + "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/db" +) + +// Seed creates n database records with dummy data +func Seed(n int) { + db.Seed(n) +} + +// Archive processes unarchived data (pageviews to aggeegated count tables) +func Archive() { + count.Archive() +} diff --git a/commands/server.go b/commands/server.go index ea01cc6..e4d2a84 100644 --- a/commands/server.go +++ b/commands/server.go @@ -2,16 +2,16 @@ package commands import ( "fmt" - "log" - "net/http" - "os" - "github.com/dannyvankooten/ana/api" "github.com/gorilla/handlers" "github.com/gorilla/mux" + "net/http" + "os" ) -func startServer(port int) { +// Server starts the HTTP server, listening on the given port +func Server(port int) { + // register routes r := mux.NewRouter() r.HandleFunc("/collect", api.CollectHandler).Methods("GET") @@ -33,6 +33,7 @@ func startServer(port int) { r.Path("/tracker.js").Handler(http.FileServer(http.Dir("./static/js/"))) r.Handle("/", http.FileServer(http.Dir("./views/"))) - log.Printf("API server is now listening on :%d", port) - http.ListenAndServe(fmt.Sprintf(":%d", port), handlers.LoggingHandler(os.Stdout, r)) + fmt.Printf("HTTP server will now start listening on :%d\n", port) + err := http.ListenAndServe(fmt.Sprintf(":%d", port), handlers.LoggingHandler(os.Stdout, r)) + fmt.Println(err) } diff --git a/commands/users.go b/commands/users.go index 1c57c3d..5292ead 100644 --- a/commands/users.go +++ b/commands/users.go @@ -1,35 +1,20 @@ package commands import ( - "log" - + "fmt" "github.com/dannyvankooten/ana/db" "github.com/dannyvankooten/ana/models" "golang.org/x/crypto/bcrypt" ) -func createUser() { - if emailArg == "" || passwordArg == "" { - log.Fatal("Please supply -email and -password values") - } - - hash, _ := bcrypt.GenerateFromPassword([]byte(passwordArg), 10) +// Register creates a new user with the given email & password +func Register(email string, password string) { + hash, _ := bcrypt.GenerateFromPassword([]byte(password), 10) user := models.User{ - Email: emailArg, + Email: email, Password: string(hash), } user.Save(db.Conn) - log.Printf("User %s #%d created", emailArg, user.ID) -} - -func deleteUser() { - if emailArg == "" && idArg == 0 { - log.Fatal("Please supply an -email or -id value") - } - - stmt2, _ := db.Conn.Prepare("DELETE FROM users WHERE email = ? OR id = ?") - stmt2.Exec(emailArg, idArg) - - log.Printf("User with email %s or ID %d deleted", emailArg, idArg) + fmt.Printf("User %s #%d created.\n", email, user.ID) }