⛳ alerts for any ctfd instance via ntfy

Compare changes

Choose any two refs to compare.

+5 -5
.direnv/bin/nix-direnv-reload
···
#!/usr/bin/env bash
set -e
-
if [[ ! -d "/home/kierank/Projects/ctfd-alerts" ]]; then
+
if [[ ! -d "/home/kierank/code/personal/ctfd-alerts" ]]; then
echo "Cannot find source directory; Did you move it?"
-
echo "(Looking for "/home/kierank/Projects/ctfd-alerts")"
+
echo "(Looking for "/home/kierank/code/personal/ctfd-alerts")"
echo 'Cannot force reload with this script - use "direnv reload" manually and then try again'
exit 1
fi
# rebuild the cache forcefully
-
_nix_direnv_force_reload=1 direnv exec "/home/kierank/Projects/ctfd-alerts" true
+
_nix_direnv_force_reload=1 direnv exec "/home/kierank/code/personal/ctfd-alerts" true
# Update the mtime for .envrc.
# This will cause direnv to reload again - but without re-building.
-
touch "/home/kierank/Projects/ctfd-alerts/.envrc"
+
touch "/home/kierank/code/personal/ctfd-alerts/.envrc"
# Also update the timestamp of whatever profile_rc we have.
# This makes sure that we know we are up to date.
-
touch -r "/home/kierank/Projects/ctfd-alerts/.envrc" "/home/kierank/Projects/ctfd-alerts/.direnv"/*.rc
+
touch -r "/home/kierank/code/personal/ctfd-alerts/.envrc" "/home/kierank/code/personal/ctfd-alerts/.direnv"/*.rc
.github/images/out.gif

This is a binary file and will not be displayed.

+75
.github/workflows/release.yml
···
+
name: Release
+
+
on:
+
release:
+
types: [created]
+
+
jobs:
+
build-and-upload:
+
runs-on: ubuntu-latest
+
permissions:
+
contents: write
+
+
steps:
+
- name: Checkout repository
+
uses: actions/checkout@v4
+
+
- name: Install Nix
+
uses: DeterminateSystems/nix-installer-action@main
+
+
- name: Configure Nix cache
+
uses: DeterminateSystems/magic-nix-cache-action@main
+
+
- name: Build for all platforms
+
run: |
+
nix develop -c ctfd-alerts-build
+
+
- name: Upload Linux AMD64 binary
+
uses: actions/upload-release-asset@v1
+
env:
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
with:
+
upload_url: ${{ github.event.release.upload_url }}
+
asset_path: ./bin/ctfd-alerts-linux-amd64
+
asset_name: ctfd-alerts-linux-amd64
+
asset_content_type: application/octet-stream
+
+
- name: Upload Linux ARM64 binary
+
uses: actions/upload-release-asset@v1
+
env:
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
with:
+
upload_url: ${{ github.event.release.upload_url }}
+
asset_path: ./bin/ctfd-alerts-linux-arm64
+
asset_name: ctfd-alerts-linux-arm64
+
asset_content_type: application/octet-stream
+
+
- name: Upload macOS AMD64 binary
+
uses: actions/upload-release-asset@v1
+
env:
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
with:
+
upload_url: ${{ github.event.release.upload_url }}
+
asset_path: ./bin/ctfd-alerts-darwin-amd64
+
asset_name: ctfd-alerts-darwin-amd64
+
asset_content_type: application/octet-stream
+
+
- name: Upload macOS ARM64 binary
+
uses: actions/upload-release-asset@v1
+
env:
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
with:
+
upload_url: ${{ github.event.release.upload_url }}
+
asset_path: ./bin/ctfd-alerts-darwin-arm64
+
asset_name: ctfd-alerts-darwin-arm64
+
asset_content_type: application/octet-stream
+
+
- name: Upload Windows AMD64 binary
+
uses: actions/upload-release-asset@v1
+
env:
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
with:
+
upload_url: ${{ github.event.release.upload_url }}
+
asset_path: ./bin/ctfd-alerts-windows-amd64.exe
+
asset_name: ctfd-alerts-windows-amd64.exe
+
asset_content_type: application/octet-stream
+1
.gitignore
···
.envrc
config.toml
cache.json
+
vendor
+25 -2
README.md
···
Sends alerts for any arbitrary [CTFd](https://ctfd.io/) instance via [ntfy](https://ntfy.sh/)
+
![vhs gif of the command being run](https://github.com/taciturnaxolotl/ctfd-alerts/blob/main/.github/images/out.gif?raw=true)
+
## Install
You can download a pre-built binary from the releases or you can use the following options
···
# Go
go install github.com/taciturnaxolotl/ctfd-alerts@latest
```
+
+
If you need a systemd service file there is one in `ctfd-alerts.service`
### Nix
···
```nix
# In your flake.nix
{
-
inputs.akami.url = "github:taciturnaxolotl/ctfd-alerts";
+
inputs.ctfd-alerts.url = "github:taciturnaxolotl/ctfd-alerts";
-
outputs = { self, nixpkgs, akami, ... }: {
+
outputs = { self, nixpkgs, ctfd-alerts, ... }: {
# Access the package as:
# ctfd-alerts.packages.${system}.default
};
}
+
```
+
+
## Config
+
+
The config for the bot is quite simple. Create a `config.toml` file in the same directory as the binary (or link to the config location with `-c ./path/to/config/config.toml`) with the following format:
+
+
```toml
+
debug = true
+
interval = 100 # defaults to 300 if unset
+
user = "echo_kieran"
+
+
[ctfd]
+
api_base = "http://163.11.237.79/api/v1"
+
api_key = "ctfd_10698fd44950bf7556bc3f5e1012832dae5bddcffb1fe82191d8dd3be3641393"
+
+
[ntfy]
+
api_base = "https://ntfy.sh/"
+
acess_token = ""
+
topic = "youralert"
```
Written in go. If you have any suggestions or issues feel free to open an issue on my [tangled](https://tangled.sh/@dunkirk.sh/ctfd-alerts) knot
+15
cassette.tape
···
+
Output .github/images/out.gif
+
Set Shell zsh
+
Set Width 1400
+
Set Height 900
+
Require ctfd-alerts-dev
+
Sleep 1s
+
Type "ctfd-alerts-dev"
+
Enter
+
Sleep 3s
+
Type "ctfd-alerts-dev status"
+
Enter
+
Sleep 4s
+
Type "ctfd-alerts-dev serve"
+
Enter
+
Sleep 5s
-12
config.toml
···
-
debug = true
-
interval = 100
-
user = "echo_kieran"
-
-
[ctfd]
-
api_base = "http://163.11.237.79/api/v1"
-
api_key = "ctfd_10698fd44950bf7556bc3f5e1012832dae5bddcffb1fe82191d8dd3be3641393"
-
-
[ntfy]
-
api_base = "https://ntfy.sh/"
-
acess_token = ""
-
topic = "cugencyber_ctfd"
+16
ctfd-alerts.service
···
+
[Unit]
+
Description=ctfd alerts server
+
After=network.target
+
+
+
[Service]
+
ExecStart=/home/pi/go/bin/ctfd-alerts serve
+
Restart=always
+
User=pi
+
WorkingDirectory=/home/pi/ctfd-alerts
+
StandardOutput=journal
+
StandardError=journal
+
LimitNOFILE=65536
+
+
[Install]
+
WantedBy=multi-user.target
+1 -1
flake.nix
···
packages = forAllSystems ({ pkgs }: {
default = pkgs.buildGoModule {
pname = "ctfd-alerts";
-
version = "0.0.1";
+
version = "0.1.0";
subPackages = [ "." ]; # Build from root directory
src = self;
vendorHash = null;
+2 -7
go.mod
···
require (
github.com/charmbracelet/fang v0.2.0
+
github.com/charmbracelet/lipgloss v1.1.0
github.com/pelletier/go-toml/v2 v2.2.4
github.com/spf13/cobra v1.9.1
)
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
-
github.com/charmbracelet/bubbles v0.21.0 // indirect
-
github.com/charmbracelet/bubbletea v1.3.4 // indirect
github.com/charmbracelet/colorprofile v0.3.1 // indirect
-
github.com/charmbracelet/lipgloss v1.1.0 // indirect
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1 // indirect
github.com/charmbracelet/x/ansi v0.9.3 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250623112707-45752038d08d // indirect
+
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
-
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
-
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
-
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/mango v0.2.0 // indirect
github.com/muesli/mango-cobra v1.2.0 // indirect
···
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
-
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.26.0 // indirect
)
+1 -15
go.sum
···
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
-
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
-
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
-
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
-
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
github.com/charmbracelet/fang v0.2.0 h1:F2sK2Zjy9kRYz/xUSF1o89DNj2BHKpxVKT7TA21KZi0=
···
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250623112707-45752038d08d h1:Y34SmGfNOuc7NxbbSXJDvIDv3BFNhj4LGWPxqk+YoNo=
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250623112707-45752038d08d/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
-
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
-
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
+
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
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/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
-
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
-
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
-
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ=
···
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
-
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
-
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=