forked from fabianonline/telegram.sh
-
Notifications
You must be signed in to change notification settings - Fork 0
/
telegram
executable file
·397 lines (353 loc) · 10.7 KB
/
telegram
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
#!/bin/bash
VERSION="0.2"
TOKEN=""
CHATS=()
DEBUG=false
DRY_RUN=false
IMAGE_FILE=""
DOCUMENT_FILE=""
PARSE_MODE=""
CODE_MODE=0
CRON_MODE=0
ACTION=""
DISABLE_WEB_PAGE_PREVIEW=false
DISABLE_NOTIFICATION=false
URL="https://api.telegram.org/bot"
FILE_URL="https://api.telegram.org/file/bot"
CURL_OPTIONS="-s"
HAS_JQ=false
hash jq >/dev/null 2>&1 && HAS_JQ=true
function help {
version
echo "Usage: $0 [options] [message]"
echo
echo "OPTIONS are:"
echo " -t <TOKEN> Telegram bot token to use. See ENVIRONMENT for more information."
echo " -c <CHAT_ID> Chat to use as recipient. Can be given more than once. See ENVIRONMENT for more information."
echo " -f <FILE> Sends file."
echo " -i <FILE> Sends file as image. This will fail if the file isn't an actual image file."
echo " -M Enables Markdown processing at telegram."
echo " -H Enables HTML processing at telegram."
echo " -C Sends text as monospace code. Useful when piping command outputs into this tool."
echo " -r Like -C, but if the first line starts with '+ ', it is specially formatted."
echo " -l Fetch known chat_ids."
echo " -R Receive a file sent via telegram."
echo " -D Sets disable_web_page_preview parameter to, well, disable the preview for links to webpages."
echo " Can also be set in config as TELEGRAM_DISABLE_WEB_PAGE_PREVIEW=true (see ENVIRONMENT)"
echo " This feature is only supported for text messages, not when sending files or images (-f, -i)."
echo " -N Diables notifications on clients. Users will receive a notification with no sound."
echo " Can also be set in config as TELEGRAM_DISABLE_NOTIFICATION=true (see ENVIRONMENT)"
echo
echo "DEBUGGING OPTIONS are:"
echo " -v Display lots of more or less useful information."
echo " -j Pretend you don't have JQ installed."
echo " -n Dry-run - don't send messages, only print them on screen."
echo
echo "Message can be '-', in that case STDIN will be used."
echo
echo "ENVIRONMENT"
echo " TOKEN and CHAT_ID are required. You can set them in four different ways:"
echo " 1) globally in /etc/telegram.sh.conf"
echo " 2) user-local in ~/.telegram.sh"
echo " 3) via environment variables TELEGRAM_TOKEN and TELEGRAM_CHAT"
echo " 4) via options -t and -c"
echo " Later methods overwrite earlier settings, so you can easily override global settings."
echo " Please be aware that you shuld keep your telegram token secret!"
echo
exit
}
function version {
echo "telegram.sh version $VERSION"
echo "by Fabian Schlenz"
}
function list_chats {
log "$URL$TOKEN"
response=`curl $CURL_OPTIONS $URL$TOKEN/getUpdates`
log "$response"
if [ "$HAS_JQ" = true ]; then
echo "These are the available chats that I can find right now. The ID is the number at the front."
echo "If there are no chats or the chat you are looking for isn't there, run this command again"
echo "after sending a message to your bot via telegram."
echo
jq -r '.result | .[].message.chat | "\(.id|tostring) - \(.first_name) \(.last_name) (@\(.username))"' 2>/dev/null <<< "$response" || {
echo "Could not parse reponse from Telegram."
echo "Response was: $response"
exit 1
}
else
echo "You don't have jq installed. I'm afraid I can't parse the JSON from telegram without it."
echo "So I'll have you do it. ;-)"
echo
echo "Please look for your chat_id in this output by yourself."
echo 'Look for something like "chat":{"id":<CHAT_ID> and verify that first_name, last_name and'
echo "username match your expected chat."
echo
echo "If there are no chats listed or the chat you are looking for isn't there, try again after"
echo "sending a message to your bot via telegram."
echo
echo $response
fi
}
function receive_file {
if [ "$HAS_JQ" = false ]; then
echo "You need to have jq installed in order to be able to download files."
exit 1
fi
result=`curl $CURL_OPTIONS $URL$TOKEN/getUpdates?allowed_updates=message`
log "$result"
# {"ok":true,"result":[
# {
# "update_id":441727866,
# "message":{
# "message_id":8339,
# "from":{"id":15773,"is_bot":false,"first_name":"Fabian","last_name":"Schlenz","username":"fabianonline","language_code":"de"},
# "chat":{"id":15773,"first_name":"Fabian","last_name":"Schlenz","username":"fabianonline","type":"private"},
# "date":1526564127,
# "document":{"file_name":"desktop.ini","file_id":"BQAav-HkXugI","file_size":282}}}]}
file_id=`jq -r '.result[-1].message.document.file_id' <<< "$result"`
log "file_id: $file_id"
if [ "$file_id" == "null" ]; then
echo "Last message received apparently didn't contain a file. Aborting."
exit 1
fi
file_name=`jq -r '.result[-1].message.document.file_name' <<< "$result"`
log "file_name: $file_name"
result=`curl $CURL_OPTIONS $URL$TOKEN/getFile?file_id=$file_id`
log $result
# {"ok":true,"result":{"file_id":"BQAav-HkXugI","file_size":282,"file_path":"documents/file_271.ini"}}
path=`jq -r '.result.file_path' <<< "$result"`
log "path: $path"
if [ "$path" == "null" ]; then
echo "Could not parse telegram's response to getFile. Aborting."
exit 1
fi
file_name="`date +%s`_$file_name"
log "file_name: $file_name"
if [ -e "$file_name" ]; then
echo "File $file_name already exists. This is unexpected, so I'm quitting now."
exit 1
fi
curl $FILE_URL$TOKEN/$path --output "$file_name"
echo "File downloaded as $file_name"
}
function log {
[ "$DEBUG" = true ] && echo "DEBUG: $1"
}
function check_file {
if [ ! -e "$1" ]; then
echo "The file $1 does not exist."
exit 1
fi
size=$(stat -c%s "$1")
if (( size > 52428800 )); then
echo "File $1 is breaking the file size limit imposed on Telegram bots (currently 50MB)."
exit 1
fi
}
function escapeMarkdown {
res="${1//\*/∗}"
res="${res//_/_}"
res="${res//\`/‵}"
#res="${res//\//∕}"
echo "$res"
}
while getopts "t:c:i:f:MHCrhlvjnRDN" opt; do
case $opt in
t)
TOKEN="$OPTARG"
;;
c)
CHATS+=("$OPTARG")
;;
i)
IMAGE_FILE="$OPTARG"
;;
f)
DOCUMENT_FILE="$OPTARG"
;;
M)
PARSE_MODE="Markdown"
;;
H)
PARSE_MODE="HTML"
;;
C)
PARSE_MODE="Markdown"
CODE_MODE=1
;;
r)
PARSE_MODE="Markdown"
CRON_MODE=1
;;
l)
ACTION="list_chats"
;;
v)
DEBUG=true
;;
j)
HAS_JQ=false
;;
n)
DRY_RUN=true
;;
R)
ACTION="receive_file"
;;
D)
DISABLE_WEB_PAGE_PREVIEW=true
;;
N)
DISABLE_NOTIFICATION=true
;;
?|h)
help
;;
:)
echo "Option -$OPTARG needs an argument."
exit 1
;;
\?)
echo "Invalid option -$OPTARG"
exit 1
;;
esac
done
if [ "$CRON_MODE" -eq 1 ] && [ "$CODE_MODE" -eq 1 ]; then
echo "You can either use -C or -r, but not both."
exit 1
fi
log "TOKEN is now $TOKEN"
log "CHATS is now ${CHATS[*]}"
[ -z "$TOKEN" ] && TOKEN=$TELEGRAM_TOKEN
[ ${#CHATS[@]} -eq 0 ] && CHATS=($TELEGRAM_CHAT)
log "TOKEN is now $TOKEN"
log "CHATS is now ${CHATS[*]}"
log "Importing config file(s)..."
[ -r /etc/telegram.sh.conf ] && source /etc/telegram.sh.conf
[ -r ~/.telegram.sh ] && source ~/.telegram.sh
[ -z "$TOKEN" ] && TOKEN=$TELEGRAM_TOKEN
[ ${#CHATS[@]} -eq 0 ] && CHATS=($TELEGRAM_CHAT)
[ -n "$TELEGRAM_DISABLE_WEB_PAGE_PREVIEW" ] && DISABLE_WEB_PAGE_PREVIEW="$TELEGRAM_DISABLE_WEB_PAGE_PREVIEW"
[ -n "$TELEGRAM_DISABLE_NOTIFICATION" ] && DISABLE_NOTIFICATION="$TELEGRAM_DISABLE_NOTIFICATION"
log "TOKEN is now $TOKEN"
log "CHATS is now ${CHATS[*]}"
log "DISABLE_WEB_PAGE_PREVIEW is now $DISABLE_WEB_PAGE_PREVIEW"
log "DISABLE_NOTIFICATION is now $DISABLE_NOTIFICATION"
if [ -z "$TOKEN" ]; then
echo "No bot token was given."
exit 1
fi
if [ ${#CHATS[@]} -eq 0 ] && [ -z "$ACTION" ]; then
echo "No chat(s) given."
exit 1
fi
if [ "$ACTION" = "list_chats" ]; then
list_chats
exit 0
fi
if [ "$ACTION" = "receive_file" ]; then
receive_file
exit 0
fi
shift $((OPTIND - 1))
TEXT="$1"
log "Text: $TEXT"
[ "$TEXT" = "-" ] && TEXT=$(</dev/stdin)
log "Text: $TEXT"
if [ $CODE_MODE -eq 1 ]; then
TEXT='```'$'\n'$TEXT$'\n''```'
fi
if [ $CRON_MODE -eq 1 ]; then
ONLY_COMMANDS=1
while read line; do
if [ "${line:0:2}" = "+ " ]; then
ONLY_COMMANDS=0
fi
done <<< "$TEXT"
if [ "$ONLY_COMMANDS" -eq 1 ]; then
exit 0
fi
TEXT='```'$'\n'$TEXT$'\n''```'
#FIRST_LINE=1
#BLOCK_OPEN=0
#NEW_TEXT=""
#while read line; do
# if [ "${line:0:2}" = "+ " ]; then
# if [ "$BLOCK_OPEN" -eq 1 ]; then
# NEW_TEXT="$NEW_TEXT"'```'$'\n'
# BLOCK_OPEN=0
# fi
# NEW_TEXT="$NEW_TEXT*`escapeMarkdown "${line:2}"`*"$'\n'
# else
# if [ "$BLOCK_OPEN" -eq 0 ]; then
# NEW_TEXT="$NEW_TEXT"'```'$'\n'
# BLOCK_OPEN=1
# fi
# NEW_TEXT="$NEW_TEXT$line"$'\n'
# fi
#done <<< "$TEXT"
#[ "$BLOCK_OPEN" -eq 1 ] && NEW_TEXT="$NEW_TEXT"'```'
#TEXT="$NEW_TEXT"
fi
log "Text: $TEXT"
if [ -z "$TEXT" ] && [ -z "$DOCUMENT_FILE" ] && [ -z "$IMAGE_FILE" ]; then
echo "Neither text nor image or other file given."
exit 1
fi
if [ -n "$DOCUMENT_FILE" ] && [ -n "$IMAGE_FILE" ]; then
echo "You can't send a file AND an image at the same time."
exit 1
fi
if [ -n "$DOCUMENT_FILE" ]; then
check_file "$DOCUMENT_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form document=@$DOCUMENT_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form caption=<-"
METHOD="sendDocument"
elif [ -n "$IMAGE_FILE" ]; then
check_file "$IMAGE_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form photo=@$IMAGE_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form caption=<-"
METHOD="sendPhoto"
else
CURL_OPTIONS="$CURL_OPTIONS --form text=<-"
[ -n "$PARSE_MODE" ] && CURL_OPTIONS="$CURL_OPTIONS --form-string parse_mode=$PARSE_MODE"
[ "$DISABLE_WEB_PAGE_PREVIEW" = true ] && CURL_OPTIONS="$CURL_OPTIONS --form-string disable_web_page_preview=true"
METHOD="sendMessage"
fi
[ "$DISABLE_NOTIFICATION" = true ] && CURL_OPTIONS="$CURL_OPTIONS --form-string disable_notification=true"
for id in "${CHATS[@]}"; do
MY_CURL_OPTIONS="$CURL_OPTIONS --form-string chat_id=$id $URL$TOKEN/$METHOD"
if [ "$DRY_RUN" = true ]; then
echo "Executing: curl $MY_CURL_OPTIONS"
echo " Text: $TEXT"
echo
status=0
response='{"ok": true}'
else
response=`curl $MY_CURL_OPTIONS <<< "$TEXT"`
status=$?
fi
log "Response was: $response"
if [ $status -ne 0 ]; then
echo "curl reported an error. Exit code was: $status."
echo "Response was: $response"
echo "Quitting."
exit $status
fi
if [ "$HAS_JQ" = true ]; then
if [ "`jq -r '.ok' <<< "$response"`" != "true" ]; then
echo "Telegram reported following error:"
jq -r '"\(.error_code): \(.description)"' <<< "$response"
echo "Quitting."
exit 1
fi
else
if [[ "$response" != '{"ok":true'* ]]; then
echo "Telegram reported an error:"
echo $response
echo "Quitting."
exit 1
fi
fi
done