feat(scripts): Telegram message includes employer, title, posting links
Made-with: Cursor
This commit is contained in:
parent
3d6dda35b0
commit
ae7e50fa91
@ -6,6 +6,9 @@ TELEGRAM_BOT_TOKEN=""
|
||||
TELEGRAM_CHAT_ID=""
|
||||
JOBOPS_URL="http://127.0.0.1:3005"
|
||||
|
||||
# Optional: cap how many job lines (title + link) are appended to the Telegram message (default 25).
|
||||
# JOB_TELEGRAM_MAX_JOBS=25
|
||||
|
||||
# Optional — only if BASIC_AUTH_USER / BASIC_AUTH_PASSWORD are set in Jobber .env
|
||||
# BASIC_AUTH_USER=""
|
||||
# BASIC_AUTH_PASSWORD=""
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run Jobber pipeline, wait until it finishes, send summary to Telegram.
|
||||
# Run Jobber pipeline, wait until it finishes, send summary + job links to Telegram.
|
||||
# Secrets: copy scripts/jobber-cron.env.example to /root/.jobber-cron.env (chmod 600).
|
||||
set -euo pipefail
|
||||
|
||||
@ -15,37 +15,110 @@ source "$ENV_FILE"
|
||||
: "${TELEGRAM_CHAT_ID:?Set TELEGRAM_CHAT_ID in $ENV_FILE}"
|
||||
|
||||
BASE="${JOBOPS_URL:-http://127.0.0.1:3005}"
|
||||
MAX_JOBS="${JOB_TELEGRAM_MAX_JOBS:-25}"
|
||||
AUTH=()
|
||||
if [[ -n "${BASIC_AUTH_USER:-}" && -n "${BASIC_AUTH_PASSWORD:-}" ]]; then
|
||||
AUTH=(-u "${BASIC_AUTH_USER}:${BASIC_AUTH_PASSWORD}")
|
||||
fi
|
||||
|
||||
send_tg() {
|
||||
tg_html_escape() {
|
||||
printf '%s' "$1" | sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g'
|
||||
}
|
||||
|
||||
tg_href_escape() {
|
||||
printf '%s' "$1" | sed -e 's/&/\&/g' -e 's/"/\"/g'
|
||||
}
|
||||
|
||||
send_tg_html() {
|
||||
local msg="$1"
|
||||
curl -sS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg c "$TELEGRAM_CHAT_ID" --arg t "$msg" '{chat_id: $c, text: $t}')" >/dev/null
|
||||
-d "$(jq -n \
|
||||
--arg c "$TELEGRAM_CHAT_ID" \
|
||||
--arg t "$msg" \
|
||||
'{chat_id: $c, text: $t, parse_mode: "HTML", disable_web_page_preview: true}')" >/dev/null
|
||||
}
|
||||
|
||||
fetch_status() {
|
||||
curl -sS "${AUTH[@]}" "${BASE}/api/pipeline/status"
|
||||
}
|
||||
|
||||
fetch_jobs_list() {
|
||||
curl -sS "${AUTH[@]}" "${BASE}/api/jobs?view=list"
|
||||
}
|
||||
|
||||
build_job_lines_html() {
|
||||
local jobs_json="$1"
|
||||
local started="$2"
|
||||
local completed="$3"
|
||||
local max_n="$4"
|
||||
|
||||
echo "$jobs_json" | jq -c --arg s "$started" --arg e "$completed" --argjson max "$max_n" '
|
||||
def pickurl:
|
||||
if (.jobUrl // "") != "" then .jobUrl
|
||||
elif (.applicationLink // "") != "" then .applicationLink
|
||||
else "" end;
|
||||
def pickrows($all):
|
||||
($all | map(select($s != "" and $e != "" and (.discoveredAt >= $s) and (.discoveredAt <= $e)))) as $win |
|
||||
if ($win | length) > 0 then $win
|
||||
else ($all | map(select($s != "" and (.discoveredAt >= $s))))
|
||||
end;
|
||||
(.data.jobs // []) as $all |
|
||||
if ($all | length) == 0 then
|
||||
{total: 0, lines: []}
|
||||
else
|
||||
(pickrows($all) | sort_by(.discoveredAt) | reverse) as $sorted |
|
||||
($sorted | length) as $total |
|
||||
($sorted | .[0:max]) as $slice |
|
||||
{
|
||||
total: $total,
|
||||
lines: [
|
||||
$slice[] |
|
||||
{
|
||||
title: (.title // "Untitled"),
|
||||
url: pickurl,
|
||||
employer: (.employer // "")
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
'
|
||||
}
|
||||
|
||||
append_lines_from_json() {
|
||||
local sel="$1"
|
||||
local -n _out="$2"
|
||||
local item line title url emp
|
||||
while IFS= read -r item; do
|
||||
[[ -z "$item" || "$item" == "null" ]] && continue
|
||||
title="$(echo "$item" | jq -r '.title // "Untitled"')"
|
||||
url="$(echo "$item" | jq -r '.url // ""')"
|
||||
emp="$(echo "$item" | jq -r '.employer // ""')"
|
||||
if [[ -n "$url" && "$url" != "null" ]]; then
|
||||
line="$(tg_html_escape "$emp") — <a href=\"$(tg_href_escape "$url")\">$(tg_html_escape "$title")</a>"
|
||||
else
|
||||
line="$(tg_html_escape "$emp") — $(tg_html_escape "$title") <i>(no URL)</i>"
|
||||
fi
|
||||
_out+=$'\n'"${line}"
|
||||
done < <(echo "$sel" | jq -c '.lines[]? // empty')
|
||||
}
|
||||
|
||||
body="$(fetch_status)"
|
||||
if ! echo "$body" | jq -e '.ok == true' >/dev/null 2>&1; then
|
||||
send_tg "Jobber: /api/pipeline/status failed (before run). Check container."
|
||||
send_tg_html "Jobber: /api/pipeline/status failed (before run). Check container."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if echo "$body" | jq -e '.data.isRunning == true' >/dev/null 2>&1; then
|
||||
send_tg "Jobber: pipeline already running; skipping scheduled run."
|
||||
send_tg_html "Jobber: pipeline already running; skipping scheduled run."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
resp="$(curl -sS "${AUTH[@]}" -X POST "${BASE}/api/pipeline/run" \
|
||||
-H "Content-Type: application/json" -d '{}')"
|
||||
if ! echo "$resp" | jq -e '.ok == true' >/dev/null 2>&1; then
|
||||
send_tg "Jobber: POST /api/pipeline/run failed: $(echo "$resp" | jq -c .)"
|
||||
_fail_json="$(echo "$resp" | jq -c . 2>/dev/null || echo "$resp")"
|
||||
send_tg_html "Jobber: POST /api/pipeline/run failed: $(tg_html_escape "$_fail_json")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -54,7 +127,7 @@ for _ in $(seq 1 720); do
|
||||
sleep 30
|
||||
body="$(fetch_status)"
|
||||
if ! echo "$body" | jq -e '.ok == true' >/dev/null 2>&1; then
|
||||
send_tg "Jobber: status check failed mid-run."
|
||||
send_tg_html "Jobber: status check failed mid-run."
|
||||
exit 1
|
||||
fi
|
||||
running="$(echo "$body" | jq -r '.data.isRunning')"
|
||||
@ -66,12 +139,37 @@ for _ in $(seq 1 720); do
|
||||
disc="$(echo "$lr" | jq -r '.jobsDiscovered // 0')"
|
||||
proc="$(echo "$lr" | jq -r '.jobsProcessed // 0')"
|
||||
err="$(echo "$lr" | jq -r '.errorMessage // empty')"
|
||||
msg="Jobber pipeline finished: ${st}. Discovered: ${disc}, processed: ${proc}."
|
||||
[[ -n "$err" ]] && msg="${msg}"$'\n'"Error: ${err}"
|
||||
send_tg "$msg"
|
||||
started="$(echo "$lr" | jq -r '.startedAt // ""')"
|
||||
completed="$(echo "$lr" | jq -r '.completedAt // ""')"
|
||||
|
||||
msg="<b>Jobber</b> pipeline: <b>$(tg_html_escape "$st")</b>"
|
||||
msg+=$'\n'"Discovered: ${disc}, processed: ${proc}."
|
||||
[[ -n "$err" ]] && msg+=$'\n'"<b>Error:</b> $(tg_html_escape "$err")"
|
||||
|
||||
jobs_resp="$(fetch_jobs_list)"
|
||||
if echo "$jobs_resp" | jq -e '.ok == true' >/dev/null 2>&1; then
|
||||
sel="$(build_job_lines_html "$jobs_resp" "$started" "$completed" "$MAX_JOBS")" ||
|
||||
sel='{"total":0,"lines":[]}'
|
||||
total="$(echo "$sel" | jq -r '.total // 0')"
|
||||
shown="$(echo "$sel" | jq -r '.lines | length')"
|
||||
if [[ "$total" -gt 0 ]]; then
|
||||
msg+=$'\n\n'"<b>Jobs in this run</b> (showing ${shown} of ${total}):"
|
||||
append_lines_from_json "$sel" msg
|
||||
rest=$((total - shown))
|
||||
if [[ "$rest" -gt 0 ]]; then
|
||||
msg+=$'\n\n'"<i>…and ${rest} more not shown.</i>"
|
||||
fi
|
||||
else
|
||||
msg+=$'\n\n'"<i>No job rows matched this run window (time filter). Open the app for the full list.</i>"
|
||||
fi
|
||||
else
|
||||
msg+=$'\n\n'"<i>Could not load GET /api/jobs for links.</i>"
|
||||
fi
|
||||
|
||||
send_tg_html "$msg"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
send_tg "Jobber: timed out waiting for pipeline (6h). Check server."
|
||||
send_tg_html "Jobber: timed out waiting for pipeline (6h). Check server."
|
||||
exit 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user