-
Notifications
You must be signed in to change notification settings - Fork 2
/
telegram
executable file
·296 lines (269 loc) · 8 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
#!/usr/bin/env bash
TOKEN=""
CHATS=()
IMAGE_FILE=""
DOCUMENT_FILE=""
URL="https://api.telegram.org/bot"
METHOD="sendMessage"
FILE_URL="https://api.telegram.org/file/bot"
CURL_OPTIONS="-s"
HAS_JQ=false
hash jq >/dev/null 2>&1 && HAS_JQ=true
DEBUG=false
DRY_RUN=false
function help() {
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 " -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 Disbles 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 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"
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
}
while getopts "t:c:i:f:MHhlvjnRDN" 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"
;;
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
[ -z "$TOKEN" ] && TOKEN=$TELEGRAM_TOKEN
[ ${#CHATS[@]} -eq 0 ] && CHATS=("$TELEGRAM_CHAT")
log "TOKEN is now $TOKEN"
log "CHATS is now ${CHATS[*]}"
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"
if [ "$TEXT" = "-" ]; then
TEXT=$(</dev/stdin)
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 "$PARSE_MODE" ]; then
CURL_OPTIONS="$CURL_OPTIONS --form-string parse_mode=$PARSE_MODE"
fi
if [ -n "$DOCUMENT_FILE" ]; then
check_file "$DOCUMENT_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form document=@$DOCUMENT_FILE --form caption=<-"
METHOD="sendDocument"
elif [ -n "$IMAGE_FILE" ]; then
check_file "$IMAGE_FILE"
CURL_OPTIONS="$CURL_OPTIONS --form photo=@$IMAGE_FILE --form caption=<-"
METHOD="sendPhoto"
else
CURL_OPTIONS="$CURL_OPTIONS --form text=<-"
if [ "$DISABLE_WEB_PAGE_PREVIEW" = true ]; then
CURL_OPTIONS="$CURL_OPTIONS --form-string disable_web_page_preview=true"
fi
METHOD="sendMessage"
fi
if [ "$DISABLE_NOTIFICATION" = true ]; then
CURL_OPTIONS="$CURL_OPTIONS --form-string disable_notification=true"
fi
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
# shellcheck disable=SC2086
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