1- # .github/workflows/telegram-notifier.yml
21name : Telegram Notifier
32
43on :
1110 types : [published]
1211 workflow_dispatch :
1312 inputs :
13+ title :
14+ description : " Manual title (e.g. 📢 Announcement)"
15+ required : false
16+ default : " 📢 Manual"
1417 text :
1518 description : " Message to send"
1619 required : true
17- title :
18- description : " Optional manual title (default: 📣 Manual)"
19- required : false
20- default : " 📣 Manual"
2120 chat_id :
2221 description : " Override TG_CHAT_ID (e.g. @Channel or numeric id)"
2322 required : false
@@ -32,15 +31,15 @@ concurrency:
3231jobs :
3332 notify :
3433 runs-on : ubuntu-latest
35- environment : SANDBOX # must contain secrets TG_BOT_TOKEN and TG_CHAT_ID
34+ environment : SANDBOX # must contain secrets TG_BOT_TOKEN and TG_CHAT_ID
3635
3736 steps :
3837 - name : Checkout (for commit log)
3938 uses : actions/checkout@v4
4039 with :
4140 fetch-depth : 50
4241
43- - name : Build message (MarkdownV2 )
42+ - name : Build message (plain text )
4443 id : msg
4544 shell : bash
4645 env :
@@ -69,80 +68,69 @@ jobs:
6968 run : |
7069 set -euo pipefail
7170
72- # Telegram MarkdownV2 escaper
73- mde() {
74- sed -e 's/\\/\\\\/g' \
75- -e 's/_/\\_/g' -e 's/*/\\*/g' -e 's/\[/\\[/g' -e 's/]/\\]/g' \
76- -e 's/(/\\(/g' -e 's/)/\\)/g' -e 's/~/\\~/g' -e 's/`/\\`/g' \
77- -e 's/>/\\>/g' -e 's/#/\\#/g' -e 's/\\+/\\\\+/g' \
78- -e 's/-/\\-/g' -e 's/=/\\=/g' -e 's/|/\\|/g' -e 's/{/\\{/g' -e 's/}/\\}/g' \
79- -e 's/\./\\./g' -e 's/!/\\!/g'
80- }
81-
8271 header() {
8372 printf '%s\nRepo: %s\nBy: %s\nRef: %s\nRun: %s\n' \
84- "$(printf '%s' "$1")" \
85- "$(printf '%s' "$REPO" | mde)" \
86- "$(printf '%s' "$ACTOR" | mde)" \
87- "$(printf '%s' "$REF_NAME" | mde)" \
88- "$(printf '%s' "$RUN_URL" | mde)"
73+ "$1" "$REPO" "$ACTOR" "$REF_NAME" "$RUN_URL"
8974 }
9075
9176 MESSAGE=""
9277
9378 if [[ "$EVENT" == "workflow_dispatch" ]]; then
94- TITLE="${WD_TITLE:-📣 Manual}"
95- # Minimal manual card: Title + By + Run + your text
96- MESSAGE="$(header "$(printf '%s' "$TITLE" | mde)")"
97- MSG_ESC="$(printf '%s' "${WD_TEXT:-}" | mde)"
98- MESSAGE="${MESSAGE}\n${MSG_ESC}"
79+ TITLE="${WD_TITLE:-📢 Manual}"
80+ MESSAGE="$(header "$TITLE")"
81+ [[ -n "${WD_TEXT:-}" ]] && MESSAGE+=$'\n'"${WD_TEXT}"
9982
10083 elif [[ "$EVENT" == "push" ]]; then
10184 BEFORE="${GIT_BEFORE:-}"
10285 AFTER="$GIT_SHA"
10386
10487 if [[ -z "$BEFORE" || "$BEFORE" =~ ^0+$ ]]; then
105- mapfile -t LINES < <(git log -n 10 --pretty=format:'%s%x1f%h%x1f%an ' "$AFTER" || true)
88+ mapfile -t LINES < <(git log -n 10 --pretty=format:'%s%x1f%h' "$AFTER" || true)
10689 else
107- mapfile -t LINES < <(git log --pretty=format:'%s%x1f%h%x1f%an ' "$BEFORE..$AFTER" | head -n 10 || true)
90+ mapfile -t LINES < <(git log --pretty=format:'%s%x1f%h' "$BEFORE..$AFTER" | head -n 10 || true)
10891 fi
10992
110- COMMITS_TXT =""
93+ COMMITS =""
11194 if [[ ${#LINES[@]} -eq 0 ]]; then
112- COMMITS_TXT ="- (no commit messages found)"
95+ COMMITS ="- (no commit messages found)"
11396 else
97+ ACTOR_URL="https://github.com/${ACTOR}"
11498 for row in "${LINES[@]}"; do
115- IFS=$'\x1f' read -r subj short author <<<"$row"
116- COMMITS_TXT +="- $(printf '%s' "$ subj" | mde) ($(printf '%s' "$ short" | mde)) by $(printf '%s' "$author" | mde)\n"
99+ IFS=$'\x1f' read -r subj short <<<"$row"
100+ COMMITS +="- ${ subj} (${ short}) by ${ACTOR_URL}"$'\n'
117101 done
102+ COMMITS="${COMMITS%$'\n'}"
118103 fi
119104
120- MESSAGE="$(header '📣 Last 10 commits')\n${COMMITS_TXT}\nRepo: $(printf '%s' "$REPO_URL" | mde)"
105+ MESSAGE="$(header '📣 Last 10 commits')"
106+ MESSAGE+=$'\n'"${COMMITS}"$'\n\n'"Repo: ${REPO_URL}"
121107
122108 elif [[ "$EVENT" == "pull_request" ]]; then
123109 if [[ "$PR_ACTION" == "closed" ]]; then
124110 [[ "${PR_MERGED}" == "true" ]] && STATUS="PR merged ✅" || STATUS="PR closed ❌"
125111 else
126112 STATUS="PR updated ✏️"
127113 fi
128- MESSAGE="$(header "$(printf '%s' "$STATUS" | mde)")\n#${PR_NUMBER}: $(printf '%s' "$PR_TITLE" | mde)\n$(printf '%s' "$PR_URL" | mde)"
114+ MESSAGE="$(header "$STATUS")"
115+ MESSAGE+=$'\n'"#${PR_NUMBER}: ${PR_TITLE}"$'\n'"${PR_URL}"
129116
130117 elif [[ "$EVENT" == "release" ]]; then
131118 NAME="${REL_NAME:-$REL_TAG}"
132- MESSAGE="$(header 'Release published 🏷️')\nTag: $(printf '%s' "$REL_TAG" | mde)\nName: $(printf '%s' "$NAME" | mde)\n$(printf '%s' "$REL_URL" | mde)"
119+ MESSAGE="$(header 'Release published 🏷️')"
120+ MESSAGE+=$'\n'"Tag: ${REL_TAG}"$'\n'"Name: ${NAME}"$'\n'"${REL_URL}"
133121
134122 else
135- MESSAGE="$(header "Event: $(printf '%s' "$ EVENT" | mde) ")"
123+ MESSAGE="$(header "Event: $EVENT")"
136124 fi
137125
138- # Safe multi-line output (no stray EOF problems )
126+ # Write multi-line output safely (no EOF pitfalls )
139127 {
140128 printf 'text<<MSGEOF\n'
141129 printf '%s\n' "$MESSAGE"
142130 printf 'MSGEOF\n'
143131 } >> "$GITHUB_OUTPUT"
144132
145- - name : Send to Telegram
133+ - name : Send to Telegram (plain text)
146134 shell : bash
147135 env :
148136 TG_BOT_TOKEN : ${{ secrets.TG_BOT_TOKEN }}
@@ -154,12 +142,15 @@ jobs:
154142 CHAT_ID="${OVERRIDE_CHAT_ID:-$TG_CHAT_ID_DEFAULT}"
155143 [[ -n "${TG_BOT_TOKEN:-}" && -n "${CHAT_ID:-}" ]] || { echo "Missing TG secrets"; exit 1; }
156144
157- curl -sS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
145+ # Send as plain text (no parse_mode) so spacing/lines stay exactly as built
146+ RESP="$(curl -sS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
158147 -H 'Content-Type: application/json' \
159148 -d "$(jq -n \
160149 --arg chat_id "$CHAT_ID" \
161150 --arg text "$TEXT" \
162- '{chat_id:$chat_id, text:$text, parse_mode:"MarkdownV2", disable_web_page_preview:true}')" \
163- | jq -e '.ok == true' >/dev/null
151+ '{chat_id:$chat_id, text:$text, disable_web_page_preview:true}')")"
152+
153+ echo "Telegram response: $RESP"
154+ echo "$RESP" | jq -e '.ok == true' >/dev/null
164155
165156 echo "✅ Message sent to Telegram."
0 commit comments