From a03976137bd84120b6ca7c1fc4ef41de37a9d54f Mon Sep 17 00:00:00 2001 From: Arun Gopalpuri Date: Wed, 31 Jul 2024 16:51:53 -0700 Subject: [PATCH] using cobra cli and raw binary --- .goreleaser.yaml | 7 +--- README.md | 27 +++++++------ cmd/main.go | 102 +++++++++++++++++++++++++++++++---------------- go.mod | 7 +++- go.sum | 10 +++++ 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 40ddd9d..17b4551 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -15,13 +15,8 @@ builds: binary: global-entry-slot-notifier archives: - - format: tar.gz + - format: binary name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" - files: - - LICENSE - -checksum: - name_template: "{{ .ProjectName }}_checksums.txt" changelog: sort: asc diff --git a/README.md b/README.md index 55086b7..5628a90 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@

Global EntryGlobal EntryGlobal Entry

+ Global Entry Slot Notifier is a command-line tool that checks for available Global Entry appointment slots at specified locations -and sends notifications via native system notification or to [ntfy app](https://ntfy.sh/) (available on Android, iPhone, and Mac). +and sends notifications via native system notification or to [ntfy app](https://ntfy.sh/), available on Android, iPhone, and Mac. ## Features @@ -20,34 +21,35 @@ and sends notifications via native system notification or to [ntfy app](https:// make all ``` -2. Or Download the latest binary zip from the [releases](https://github.com/arun0009/global-entry-slot-notifier/releases) page. +2. Or Download the latest binary from the [releases](https://github.com/arun0009/global-entry-slot-notifier/releases) page + as `global-entry-slot-notifier` (with `.exe` extension for windows) - Extract the tar file and run `global-entry-slot-notifier` binary file. You may need to grant permission to run the binary. + Note: You may need to grant permission to run the binary. ### Usage ```bash - ./global-entry-slot-notifier --location --notifier [--topic ] [--interval ] + ./global-entry-slot-notifier -l -n [-t ] [-i ] ``` ### Flags -* `--location` (required): Specify the location ID for the Global Entry appointment (see below location ids). -* `--notifier` (required): Specify the notifier type (app or system). -* `--topic` (required if notifier is app): Specify the ntfy.sh [topic](https://docs.ntfy.sh/) to send notifications to. -* `--interval` (optional): Specify the interval (in seconds, e.g. 30s) at which to check for available appointments. Default is 60s. +* `-l`, `--location` (required): Specify the location ID for the Global Entry appointment (see below location ids). +* `-n`, `--notifier` (required): Specify the notifier type (app or system). +* `-t`, `--topic` (required if notifier is app): Specify the ntfy.sh [topic](https://docs.ntfy.sh/) to send notifications to. +* `-i`, `--interval` (optional): Specify the interval (in seconds, e.g. 30s) at which to check for available appointments. Default is 60s. ### Examples 1. System Notification ```bash - ./global-entry-slot-notifier --location 5446 --notifier system --interval 90s + ./global-entry-slot-notifier -l 5446 -n system -i 90s ``` 2. App Notification (first create your [topic on ntfy app](https://docs.ntfy.sh/)) ```bash - ./global-entry-slot-notifier --location 5446 --notifier app --topic my-ntfy-topic + ./global-entry-slot-notifier -l 5446 -n app -t my-ntfy-topic ``` ###### Pick your location id from below to use in flag (above) @@ -186,9 +188,8 @@ You can download the binary on [raspberry pi](https://www.raspberrypi.com/) or o and run it as background process to notify you via [ntfy.sh](https://ntfy.sh/)) ```bash -curl -L https://github.com/arun0009/global-entry-slot-notifier/releases/download/v1.0/global-entry-slot-notifier_1.0_linux_amd64.tar.gz -o global-entry-slot-notifier.tar.gz -tar -xvf global-entry-slot-notifier.tar.gz global-entry-slot-notifier - ./global-entry-slot-notifier --location 5446 --notifier app --topic my-ntfy-topic & + curl -L https://github.com/arun0009/global-entry-slot-notifier/releases/download/v1.0/global-entry-slot-notifier_1.0_linux_amd64 -o global-entry-slot-notifier + ./global-entry-slot-notifier -l 5446 -n app -t my-ntfy-topic & ``` ### License diff --git a/cmd/main.go b/cmd/main.go index b939ad9..78269c0 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,10 +1,11 @@ package main import ( + "bufio" "encoding/json" - "flag" "fmt" "github.com/gen2brain/beeep" + "github.com/spf13/cobra" "io" "log" "net/http" @@ -97,42 +98,73 @@ func appointmentCheck(url string, client HTTPClient, notifier Notifier, topic st } func main() { - // Define command-line flags - location := flag.String("location", "", "Specify the location ID") - notifierType := flag.String("notifier", "", "Specify the notifier type (app/system)") - topic := flag.String("topic", "", "Specify the ntfy topic (required if notifier is app)") - interval := flag.Duration("interval", time.Second*60, "Specify the interval") - - // Parse command-line flags - flag.Parse() - - // Validate flags - if *location == "" || *notifierType == "" || (*notifierType == "app" && *topic == "") { - fmt.Println("Both --location and --notifier flags are required. If notifier is app, --topic is required.") - flag.Usage() - os.Exit(1) + var location string + var notifierType string + var topic string + var interval time.Duration + + rootCmd := &cobra.Command{ + Use: "global-entry-slot-notifier", + Short: "Checks for appointment slots and sends notifications", + Run: func(cmd *cobra.Command, args []string) { + // Function to prompt user for input + getInput := func(prompt string) string { + reader := bufio.NewReader(os.Stdin) + fmt.Print(prompt) + input, _ := reader.ReadString('\n') + return strings.TrimSpace(input) + } + + // Check and prompt for missing flags + if location == "" { + location = getInput("Enter the location ID: ") + } + if notifierType == "" { + notifierType = getInput("Enter the notifier type (app/system): ") + } + if notifierType == "app" && topic == "" { + topic = getInput("Enter the ntfy topic: ") + } + + // Validate flags + if location == "" || notifierType == "" || (notifierType == "app" && topic == "") { + fmt.Println("Both --location and --notifier flags are required. If notifier is app, --topic is required.") + _ = cmd.Usage() + os.Exit(1) + } + + url := fmt.Sprintf(GlobalEntryUrl, location) + + var notifier Notifier + client := &http.Client{} + switch notifierType { + case "app": + notifier = AppNotifier{Client: client} + case "system": + notifier = SystemNotifier{} + default: + log.Fatalf("Unknown notifier type: %s", notifierType) + } + + // Create a closure that captures the arguments and calls appointmentCheck with them. + appointmentCheckFunc := func() { + appointmentCheck(url, client, notifier, topic) + } + + go appointmentCheckScheduler(interval, appointmentCheckFunc) + + // Keep the main function running to allow the ticker to tick. + select {} + }, } - url := fmt.Sprintf(GlobalEntryUrl, *location) - - var notifier Notifier - client := &http.Client{} - switch *notifierType { - case "app": - notifier = AppNotifier{Client: client} - case "system": - notifier = SystemNotifier{} - default: - log.Fatalf("Unknown notifier type: %s", *notifierType) - } + rootCmd.Flags().StringVarP(&location, "location", "l", "", "Specify the location ID") + rootCmd.Flags().StringVarP(¬ifierType, "notifier", "n", "", "Specify the notifier type (app or system)") + rootCmd.Flags().StringVarP(&topic, "topic", "t", "", "Specify the ntfy topic (required if notifier is app)") + rootCmd.Flags().DurationVarP(&interval, "interval", "i", time.Second*60, "Specify the interval") - // Create a closure that captures the arguments and calls appointmentCheck with them. - appointmentCheckFunc := func() { - appointmentCheck(url, client, notifier, *topic) + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - - go appointmentCheckScheduler(*interval, appointmentCheckFunc) - - // Keep the main function running to allow the ticker to tick. - select {} } diff --git a/go.mod b/go.mod index c5207e9..da72dbb 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,17 @@ module github.com/arun0009/global-entry-slot-notifier go 1.22 -require github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 +require ( + github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 + github.com/spf13/cobra v1.8.1 +) require ( github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect golang.org/x/sys v0.22.0 // indirect ) diff --git a/go.sum b/go.sum index 1b3b623..cc1e42c 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,23 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 h1:ygs9POGDQpQGLJPlq4+0LBUmMBNox1N4JSpw+OETcvI= github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4/go.mod h1:0W7dI87PvXJ1Sjs0QPvWXKcQmNERY77e8l7GFhZB/s4= github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE= github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk= github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=