debugreport functional
This commit is contained in:
parent
fd15ba3bb4
commit
08a2121ffe
|
@ -0,0 +1 @@
|
|||
build_logs
|
93
README.md
93
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.
|
|
@ -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"]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
9
go.mod
9
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
|
||||
)
|
||||
|
|
22
go.sum
22
go.sum
|
@ -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=
|
|
@ -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
|
||||
|
|
169
main.go
169
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue