diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58ebe16 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build_logs diff --git a/README.md b/README.md index c4dc726..40cb0cc 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,60 @@ -You can stream and read files to a sentry DSN glitchtip or sentry itself I was fed up with how brittle sentry-cli was so I made this. +# DebugReport -I might get around to making a whole CI/CD process for this which will upload the executables properly at some point and make this public. -# Go Glitch - -Go Glitch is a command-line utility that reads log messages from a file or stdin and sends them to Glitchtip, a self-hosted Sentry-compatible error tracking system. +DebugReport is a command-line utility designed to record terminal sessions using `asciinema`, upload the recordings to Hastebin, and send notifications to Pushover. This utility is ideal for capturing debug sessions and sharing them easily. ## Installation -To install the binary locally, you can use the provided installation script. Run the following command in your terminal: +To use DebugReport, ensure you have the `asciinema` tool installed on your system. -```sh -curl -sSL https://git.nixc.us/Nixius/go-glitch/raw/branch/master/install.sh | bash -``` +### Installing Asciinema -This will download and install the Go Glitch binary to your local machine. +You can install `asciinema` by following the instructions on their [official website](https://asciinema.org/docs/installation). ## Usage -You can use Go Glitch by specifying a log file as an argument or by piping input to it. +You can use DebugReport to record your terminal sessions, upload the recordings to Hastebin, and send notifications to Pushover. -### Using a Log File +### Start a Recording + +Run the `debugreport` command: ```sh -go-glitch /path/to/logfile +./debugreport ``` -### Using Piped Input +You will see a message indicating that the recording has started. To stop the recording, press `Ctrl+D` or type `exit`. + +### Sending Notifications + +After the recording is finished, you will be prompted to specify if the notification is a high-priority issue: + +``` +Is this a priority notification? (yes/no): +``` + +- If you answer `yes`, the notification will be sent as a high-priority (emergency) notification with a retry interval of 60 seconds and an expire time of 1800 seconds (30 minutes). +- If you answer `no`, the notification will be sent as a low-priority notification. + +## External Services + +DebugReport interacts with the following external services: + +- **Pushover**: Used to send notifications. +- **Hastebin**: Used to upload the recorded sessions. + +Ensure you have accounts and necessary credentials for these services. + +## Example ```sh -cat /path/to/logfile | go-glitch +./debugreport ``` -## Configuration +1. The program will start recording the terminal session. +2. To stop the recording, press `Ctrl+D` or type `exit`. +3. After the recording is finished, you will be prompted to specify if the notification is a high-priority issue. +4. The recording will be uploaded to Hastebin and a notification will be sent to Pushover with the recording URL. -Go Glitch requires the `GLITCHTIP_DSN` environment variable to be set with your Glitchtip DSN. You can set this environment variable in your shell environment, Dockerfile, or `docker-compose.yml` file. +## Dependencies -### Shell Environment - -Add the following line to your `.zshrc` or `.bashrc` file: - -```sh -export GLITCHTIP_DSN="your-glitchtip-dsn" -``` - -After adding the line, reload your shell configuration: - -```sh -source ~/.zshrc # for zsh users -source ~/.bashrc # for bash users -``` - -### Dockerfile - -If you are using a Docker container, add the environment variable in your `Dockerfile`: - -```Dockerfile -ENV GLITCHTIP_DSN=your-glitchtip-dsn -``` - -### docker-compose.yml - -If you are using Docker Compose, add the environment variable in your `docker-compose.yml` file: - -```yaml -version: '3.8' - -services: - go-glitch: - image: your-docker-image - environment: - - GLITCHTIP_DSN=your-glitchtip-dsn -``` +Ensure `asciinema` is installed and properly configured in your environment. \ No newline at end of file diff --git a/asciinema-20240618183800.cast b/asciinema-20240618183800.cast new file mode 100644 index 0000000..021eba5 --- /dev/null +++ b/asciinema-20240618183800.cast @@ -0,0 +1,46 @@ +{"version": 2, "width": 207, "height": 25, "timestamp": 1718750280, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}} +[0.256711, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r\u001b]2;aedev@computers-iMac:~/dev/debugreport\u0007\u001b]1;..v/debugreport\u0007"] +[0.261332, "o", "\u001b]7;file://computers-iMac.localdomain/Users/aedev/dev/debugreport\u001b\\"] +[0.276765, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[35maedev\u001b[00m\u001b[36m@\u001b[00m\u001b[33mcomputers-iMac\u001b[00m\u001b[31m:\u001b[00m\u001b[36m~/dev/debugreport\u001b[00m\u001b[31m|\u001b[00m\u001b[36m⇒\u001b[00m \u001b[K"] +[0.276846, "o", "\u001b[?1h\u001b=\u001b[?2004h"] +[1.569833, "o", "l"] +[1.585655, "o", "\b\u001b[32ml\u001b[39m"] +[1.586509, "o", "\b\u001b[32ml\u001b[39m\u001b[90ms\u001b[39m\b"] +[1.704188, "o", "\b\u001b[32ml\u001b[32ms\u001b[39m"] +[1.841041, "o", "\u001b[?1l\u001b>"] +[1.841212, "o", "\u001b[?2004l"] +[1.844016, "o", "\r\r\n"] +[1.84507, "o", "\u001b]2;ls -G\u0007\u001b]1;ls\u0007"] +[1.862516, "o", "README.md \u001b[31mbuild.sh\u001b[39;49m\u001b[0m \u001b[1m\u001b[36mdist\u001b[39;49m\u001b[0m install.sh\r\nasciinema-20240618183800.cast \u001b[1m\u001b[36mbuild_logs\u001b[39;49m\u001b[0m go.mod main.go\r\n"] +[1.862743, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[1.862912, "o", "\u001b]2;aedev@computers-iMac:~/dev/debugreport\u0007\u001b]1;..v/debugreport\u0007"] +[1.86532, "o", "\u001b]7;file://computers-iMac.localdomain/Users/aedev/dev/debugreport\u001b\\"] +[1.885521, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[35maedev\u001b[00m\u001b[36m@\u001b[00m\u001b[33mcomputers-iMac\u001b[00m\u001b[31m:\u001b[00m\u001b[36m~/dev/debugreport\u001b[00m\u001b[31m|\u001b[00m\u001b[36m⇒\u001b[00m \u001b[K"] +[1.885742, "o", "\u001b[?1h\u001b=\u001b[?2004h"] +[3.353476, "o", "o"] +[3.359874, "o", "\b\u001b[1m\u001b[31mo\u001b[0m\u001b[39m"] +[3.360155, "o", "\b\u001b[1m\u001b[31mo\u001b[0m\u001b[39m\u001b[90mpen Sandsara-tracks\u001b[39m\u001b[19D"] +[4.076455, "o", "\b\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[0m\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[18D"] +[4.195769, "o", "\b\b\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[0m\u001b[39m"] +[4.451507, "o", "\b\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m"] +[4.616607, "o", "\b\u001b[1m\u001b[31my\u001b[1m\u001b[31m \u001b[0m\u001b[39m"] +[4.619412, "o", "\b\b\u001b[1m\u001b[31my\u001b[0m\u001b[39m\u001b[0m\u001b[39m "] +[5.413241, "o", "\b\b\b\b\b"] +[5.998918, "o", "\u001b[0m\u001b[39me\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m \b\b\b\b\b"] +[6.005631, "o", "\b\u001b[1m\u001b[31me"] +[6.235222, "o", "\b\u001b[1m\u001b[31me\u001b[1m\u001b[31mc\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m \b\b\b\b\b"] +[6.331374, "o", "\u001b[1m\u001b[31mh\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m \b\b\b\b\b"] +[6.417782, "o", "\u001b[1C\u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m \b\b\b\b\b"] +[6.52071, "o", "\u001b[1m\u001b[31m \u001b[1m\u001b[31mo\u001b[1m\u001b[31mk\u001b[1m\u001b[31ma\u001b[1m\u001b[31my\u001b[0m\u001b[39m \b\b\b\b\b"] +[6.535294, "o", "\b\b\b\b\b\u001b[0m\u001b[32me\u001b[0m\u001b[32mc\u001b[0m\u001b[32mh\u001b[0m\u001b[32mo\u001b[39m\u001b[0m\u001b[39m \u001b[0m\u001b[39mo\u001b[0m\u001b[39mk\u001b[0m\u001b[39ma\u001b[0m\u001b[39my\b\b\b\b"] +[6.986127, "o", "\u001b[?1l\u001b>"] +[6.986177, "o", "\u001b[?2004l"] +[6.989743, "o", "\r\r\n"] +[6.991177, "o", "\u001b]2;echo okay\u0007\u001b]1;echo\u0007"] +[7.024897, "o", "okay\r\n"] +[7.024932, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[7.02502, "o", "\u001b]2;aedev@computers-iMac:~/dev/debugreport\u0007\u001b]1;..v/debugreport\u0007"] +[7.027346, "o", "\u001b]7;file://computers-iMac.localdomain/Users/aedev/dev/debugreport\u001b\\"] +[7.040054, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[35maedev\u001b[00m\u001b[36m@\u001b[00m\u001b[33mcomputers-iMac\u001b[00m\u001b[31m:\u001b[00m\u001b[36m~/dev/debugreport\u001b[00m\u001b[31m|\u001b[00m\u001b[36m⇒\u001b[00m \u001b[K"] +[7.040286, "o", "\u001b[?1h\u001b=\u001b[?2004h"] +[8.494716, "o", "\u001b[?2004l\r\r\n"] diff --git a/dist/debugreport_darwin_amd64 b/dist/debugreport_darwin_amd64 new file mode 100755 index 0000000..b20a53c Binary files /dev/null and b/dist/debugreport_darwin_amd64 differ diff --git a/dist/debugreport_darwin_arm64 b/dist/debugreport_darwin_arm64 new file mode 100755 index 0000000..65b1355 Binary files /dev/null and b/dist/debugreport_darwin_arm64 differ diff --git a/dist/debugreport_linux_amd64 b/dist/debugreport_linux_amd64 new file mode 100755 index 0000000..7f601ab Binary files /dev/null and b/dist/debugreport_linux_amd64 differ diff --git a/dist/debugreport_linux_amd64_static b/dist/debugreport_linux_amd64_static new file mode 100755 index 0000000..5312898 Binary files /dev/null and b/dist/debugreport_linux_amd64_static differ diff --git a/dist/debugreport_linux_arm64 b/dist/debugreport_linux_arm64 new file mode 100755 index 0000000..ad5f903 Binary files /dev/null and b/dist/debugreport_linux_arm64 differ diff --git a/dist/debugreport_linux_arm64_static b/dist/debugreport_linux_arm64_static new file mode 100755 index 0000000..6663ab9 Binary files /dev/null and b/dist/debugreport_linux_arm64_static differ diff --git a/dist/debugreport_windows_amd64 b/dist/debugreport_windows_amd64 new file mode 100755 index 0000000..87ee4ea Binary files /dev/null and b/dist/debugreport_windows_amd64 differ diff --git a/dist/go-glitch_darwin_amd64 b/dist/go-glitch_darwin_amd64 deleted file mode 100755 index b048b39..0000000 Binary files a/dist/go-glitch_darwin_amd64 and /dev/null differ diff --git a/dist/go-glitch_darwin_arm64 b/dist/go-glitch_darwin_arm64 deleted file mode 100755 index 771e1ca..0000000 Binary files a/dist/go-glitch_darwin_arm64 and /dev/null differ diff --git a/dist/go-glitch_linux_amd64 b/dist/go-glitch_linux_amd64 deleted file mode 100755 index bd822ad..0000000 Binary files a/dist/go-glitch_linux_amd64 and /dev/null differ diff --git a/dist/go-glitch_linux_amd64_static b/dist/go-glitch_linux_amd64_static deleted file mode 100755 index 20bc953..0000000 Binary files a/dist/go-glitch_linux_amd64_static and /dev/null differ diff --git a/dist/go-glitch_linux_arm64 b/dist/go-glitch_linux_arm64 deleted file mode 100755 index 39bcbea..0000000 Binary files a/dist/go-glitch_linux_arm64 and /dev/null differ diff --git a/dist/go-glitch_linux_arm64_static b/dist/go-glitch_linux_arm64_static deleted file mode 100755 index 235f6f0..0000000 Binary files a/dist/go-glitch_linux_arm64_static and /dev/null differ diff --git a/dist/go-glitch_windows_amd64 b/dist/go-glitch_windows_amd64 deleted file mode 100755 index d7bda67..0000000 Binary files a/dist/go-glitch_windows_amd64 and /dev/null differ diff --git a/go.mod b/go.mod index 2af2912..879fabf 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,3 @@ -module go-glitch +module debugreport go 1.21.1 - -require github.com/getsentry/sentry-go v0.27.0 - -require ( - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index b3daf4a..0000000 --- a/go.sum +++ /dev/null @@ -1,22 +0,0 @@ -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/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= -github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/install.sh b/install.sh index 790547d..8eed836 100644 --- a/install.sh +++ b/install.sh @@ -1,8 +1,8 @@ #!/bin/bash INSTALL_DIR="/usr/local/bin" -BINARY_NAME="go-glitch" -BASE_URL="https://git.nixc.us/Nixius/go-glitch/raw/branch/master/dist" +BINARY_NAME="debugreport" +BASE_URL="https://git.nixc.us/colin/debugreport/raw/branch/master/dist" # Supported architectures diff --git a/main.go b/main.go index 0f16b19..1f24997 100644 --- a/main.go +++ b/main.go @@ -3,16 +3,15 @@ package main import ( "bufio" "bytes" + "encoding/json" "fmt" "io" "log" "mime/multipart" - "net" "net/http" "os" "os/exec" "os/user" - "path/filepath" "strings" "time" ) @@ -22,56 +21,58 @@ const pushoverURL = "https://api.pushover.net/1/messages.json" const pushoverToken = "aunhi15sq2ervgjzyxm1msnnmucv41" const pushoverUserKey = "ujFeJyjYFJd2Lwbygfw9cSCoeYiLBi" -// Asciinema server URL -const asciinemaServerURL = "https://asciinema.nixc.us/" - -// Path to the asciinema installation ID file -const asciinemaInstallIDFile = "$HOME/.config/asciinema/install-id" +// Hastebin server URL +const hastebinServerURL = "https://haste.nixc.us/documents" func main() { - // Check if asciinema CLI is authenticated - if !isAuthenticated() { - log.Println("Asciinema CLI is not authenticated. Please run 'asciinema auth' to authenticate.") - err := runAsciinemaAuth() - if err != nil { - log.Fatalf("Failed to authenticate asciinema CLI: %v", err) - } - } - // Generate a unique filename for the asciinema recording timestamp := time.Now().Format("20060102150405") filename := fmt.Sprintf("asciinema-%s.cast", timestamp) + // Inform the user how to stop the recording + fmt.Println("Starting asciinema recording. Press Ctrl+D or type 'exit' to stop the recording.") + // Start asciinema recording - cmd := exec.Command("asciinema", "rec", "--title", "Debug Report", "--command", "bash", filename) - cmd.Env = append(os.Environ(), "ASCIINEMA_API_URL="+asciinemaServerURL) + cmd := exec.Command("asciinema", "rec", filename) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin - log.Println("Starting asciinema recording...") - err := cmd.Run() + err := cmd.Start() if err != nil { log.Fatalf("Failed to start asciinema recording: %v", err) } + err = cmd.Wait() + if err != nil { + log.Fatalf("Asciinema recording process exited with error: %v", err) + } + log.Println("Asciinema recording finished:", filename) // Collect system details hostname, _ := os.Hostname() currentUser, _ := user.Current() - ipAddress, err := getExternalIP() - if err != nil { - log.Fatalf("Failed to get external IP address: %v", err) - } // Create the message with system details - message := fmt.Sprintf("New asciinema recording from host: %s, user: %s, IP: %s", hostname, currentUser.Username, ipAddress) + message := fmt.Sprintf("New asciinema recording from host: %s, user: %s", hostname, currentUser.Username) + log.Println("Message to be sent:", message) + + // Upload the recording to Hastebin and get the URL + hastebinURL, err := uploadToHastebin(filename) + if err != nil { + log.Fatalf("Failed to upload recording to Hastebin: %v", err) + } + + // Update the message with the Hastebin URL + message = fmt.Sprintf("New asciinema recording from host: %s, user: %s, URL: %s", hostname, currentUser.Username, hastebinURL) // Ask the user if this is a priority notification isPriority := askPriority() + log.Println("Priority status:", isPriority) - // Send the recording to Pushover - err = sendToPushover(filename, message, isPriority) + // Send the updated message to Pushover + err = sendToPushover(message, isPriority) if err != nil { log.Fatalf("Failed to send recording to Pushover: %v", err) } @@ -79,51 +80,75 @@ func main() { log.Println("Recording sent to Pushover successfully.") } -// isAuthenticated checks if the asciinema CLI is authenticated -func isAuthenticated() bool { - installIDPath := os.ExpandEnv(asciinemaInstallIDFile) - _, err := os.Stat(installIDPath) - return !os.IsNotExist(err) -} - -// runAsciinemaAuth runs the asciinema auth command to authenticate the CLI -func runAsciinemaAuth() error { - cmd := exec.Command("asciinema", "auth") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} - -// sendToPushover sends the recording file and message to the Pushover URL -func sendToPushover(filename, message string, priority bool) error { +// uploadToHastebin uploads the asciinema recording to Hastebin and returns the resulting URL +func uploadToHastebin(filename string) (string, error) { file, err := os.Open(filename) if err != nil { - return fmt.Errorf("failed to open recording file: %w", err) + return "", fmt.Errorf("failed to open recording file: %w", err) } defer file.Close() + body := &bytes.Buffer{} + _, err = io.Copy(body, file) + if err != nil { + return "", fmt.Errorf("failed to copy file content: %w", err) + } + + req, err := http.NewRequest("POST", hastebinServerURL, body) + if err != nil { + return "", fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Content-Type", "text/plain") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("received non-200 response: %d", resp.StatusCode) + } + + var result struct { + Key string `json:"key"` + } + err = json.NewDecoder(resp.Body).Decode(&result) + if err != nil { + return "", fmt.Errorf("failed to decode response: %w", err) + } + + return fmt.Sprintf("https://haste.nixc.us/%s", result.Key), nil +} + +// askPriority prompts the user to specify if the notification is a priority +func askPriority() bool { + reader := bufio.NewReader(os.Stdin) + fmt.Print("Is this a priority notification? (yes/no): ") + response, err := reader.ReadString('\n') + if err != nil { + log.Fatalf("Failed to read user input: %v", err) + } + response = strings.TrimSpace(strings.ToLower(response)) + return response == "yes" +} + +// sendToPushover sends the message to the Pushover URL +func sendToPushover(message string, priority bool) error { body := &bytes.Buffer{} writer := multipart.NewWriter(body) - part, err := writer.CreateFormFile("file", filepath.Base(file.Name())) - if err != nil { - return fmt.Errorf("failed to create form file: %w", err) - } - - _, err = io.Copy(part, file) - if err != nil { - return fmt.Errorf("failed to copy file content: %w", err) - } - - // Add Pushover parameters writer.WriteField("token", pushoverToken) writer.WriteField("user", pushoverUserKey) writer.WriteField("message", message) if priority { - writer.WriteField("priority", "1") + writer.WriteField("priority", "2") + writer.WriteField("retry", "60") + writer.WriteField("expire", "1800") } - err = writer.Close() + err := writer.Close() if err != nil { return fmt.Errorf("failed to close writer: %w", err) } @@ -147,31 +172,3 @@ func sendToPushover(filename, message string, priority bool) error { return nil } - -// askPriority prompts the user to specify if the notification is a priority -func askPriority() bool { - reader := bufio.NewReader(os.Stdin) - fmt.Print("Is this a priority notification? (yes/no): ") - response, err := reader.ReadString('\n') - if err != nil { - log.Fatalf("Failed to read user input: %v", err) - } - response = strings.TrimSpace(strings.ToLower(response)) - return response == "yes" -} - -// getExternalIP fetches the current external IP address -func getExternalIP() (string, error) { - resp, err := http.Get("https://api.ipify.org") - if err != nil { - return "", fmt.Errorf("failed to get external IP: %w", err) - } - defer resp.Body.Close() - - ip, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read IP response: %w", err) - } - - return strings.TrimSpace(string(ip)), nil -}