final: prev: let lib = prev.lib; in { panoptikonReporters = (prev.panoptikonWatchers or { }) // { kpaste-irc = { target, retiolumLink ? false, server ? "irc.r", messagePrefix ? "change detected: ", nick ? ''"$PANOPTIKON_WATCHER"-watcher'', }: prev.writers.writeDash "kpaste-irc-reporter" '' KPASTE_CONTENT_TYPE=text/plain ${prev.kpaste}/bin/kpaste \ | ${prev.gnused}/bin/sed -n "${if retiolumLink then "2" else "3"}s/^/${messagePrefix}/p" \ | ${prev.nur.repos.mic92.ircsink}/bin/ircsink \ --nick ${nick} \ --server ${server} \ --target ${target} ''; irc = { target, # e.g., "#mychannel" server ? "irc.libera.chat", port ? "6667", nick ? "panoptikon-bot", messagePrefix ? "change detected: ", }: prev.writers.writeDash "irc-reporter" '' MESSAGE=$(cat | tr -d '\n\r') # Use netcat to send raw IRC commands ( echo "NICK ${nick}" echo "USER ${nick} 8 * :Panoptikon Watcher" sleep 2 # Give the server a moment to process login echo "JOIN ${target}" echo "PRIVMSG ${target} :${messagePrefix} $MESSAGE" echo "QUIT" ) | ${prev.netcat}/bin/nc -w 10 ${server} ${port} ''; telegram = { tokenPath, # Bot API Token chatId, messagePrefix ? "Change detected in $PANOPTIKON_WATCHER: ", }: prev.writers.writeDash "telegram-reporter" '' if [ ! -f "${tokenPath}" ]; then echo "Error: Token file ${tokenPath} not found" >&2 exit 1 fi TOKEN=$(cat "${tokenPath}") MESSAGE=$(cat) ${prev.curl}/bin/curl -s -X POST "https://api.telegram.org/bot''${TOKEN}/sendMessage" \ -d chat_id="${chatId}" \ -d text="${messagePrefix} $MESSAGE" ''; matrix = { homeserver, # e.g., "https://matrix.org" roomId, # e.g., "!roomid:matrix.org" tokenPath, messagePrefix ? "Change detected in $PANOPTIKON_WATCHER: ", }: prev.writers.writeDash "matrix-reporter" '' if [ ! -f "${tokenPath}" ]; then echo "Error: Token file ${tokenPath} not found" >&2 exit 1 fi TOKEN=$(cat "${tokenPath}") MESSAGE=$(cat) TXN_ID=$(date +%s%N) ${prev.curl}/bin/curl -s -X PUT "${homeserver}/_matrix/client/r0/rooms/${lib.escapeShellArg roomId}/send/m.room.message/''${TXN_ID}?access_token=''${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"msgtype\": \"m.text\", \"body\": \"${messagePrefix} $MESSAGE\"}" ''; wall = { messagePrefix ? "PANOPTIKON ALERT ($PANOPTIKON_WATCHER):", }: prev.writers.writeDash "wall-reporter" '' MESSAGE=$(cat) echo -e "${messagePrefix}\n$MESSAGE" | ${prev.util-linux}/bin/wall ''; mail = { recipient, # e.g. "admin@example.com" subjectPrefix ? "[Panoptikon] Change detected:", }: prev.writers.writeDash "mail-reporter" '' MESSAGE=$(cat) echo "$MESSAGE" | ${prev.mailutils}/bin/mail -s "${subjectPrefix} $PANOPTIKON_WATCHER" "${recipient}" ''; }; panoptikonWatchers = (prev.panoptikonWatchers or { }) // { plain = address: prev.writers.writeDash "watch-url" '' ${prev.curl}/bin/curl -sSL ${lib.escapeShellArg address} ''; html = address: prev.writers.writeDash "watch-html" '' ${prev.curl}/bin/curl -sSL ${lib.escapeShellArg address} \ | ${prev.python3Packages.html2text}/bin/html2text --decode-errors=ignore ''; htmlSelector = selector: address: prev.writers.writeDash "watch-html-selector" '' ${prev.curl}/bin/curl -sSL ${lib.escapeShellArg address} \ | ${prev.htmlq}/bin/htmlq ${lib.escapeShellArg selector} \ | ${prev.python3Packages.html2text}/bin/html2text ''; json = { jqScript ? ".", }: address: prev.writers.writeDash "watch-json" '' ${prev.curl}/bin/curl -sSL ${lib.escapeShellArg address} | ${prev.jq}/bin/jq -f ${prev.writeText "script.jq" jqScript} ''; }; }