Được tạo bởi Blogger.

Debian - Send your Server Notifications thru Telegram

As a system administrator, you must be receiving your important server notifications by emails. Email has been used since decades, but it is slowly replaced in everydays life by social networks. With social network clients, messages are usually displayed as thread and get instant notification on your smartphone.

So, why not receiving your main server notifications on one of your favorite social network client ?

Telegram is becoming a very popular social network as it is free and multi-platforms. It has also a unique feature : it's allowing the use of bots. Bots are very interesting as they can be seen as an application account associated to a real person's account. They are able to send or receive messages to/from either an individual account or a group.

So, instead of sending a mail, it could be very interesting for your Debian/Ubuntu server to be able to send you Telegram notification. You can for example create an administrator group and send all your server notifications to this group. Any administrator belonging to this Telegram group will get instant notification from the server.

This article explains how to setup a server environment to very easily send Telegram notifications from any of your server script or service. It also provides a script that allows you to send Telegram messages including text, photos, documents, logs, …

It has been tested on a Debian 8.5 server but it should work on any modern Linux distribution.

1. Pre-Requisite
1.1. Create your Telegram Bot
Telegram allows you to easily create your own Bot with the help of @BotFather.
This page explain very clearly what you can expect from your Telegram Bot and how to create it.

To make it short, a Bot is a type of Telegram account that doesn't need to be associated to a phone number. It's an application account associated to your personnal account.

Once you have created your Bot, you get your API key. This key looks like 
123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz.

As Telegram APIs are using plain httpsURL with POST data, this API key is needed to identify the Bot when you send messages, photos and documentsstraight from any web client.

All parameters are explained in Telegram API page.

Your Bot will be able to send messages either to :
your personnal account
any channel it belongs to

But to send any message, your Bot will need to use either your user ID or a Channel ID. It can not address an account simply using its name.

Here is the way to get these IDs.
1.2. Get your User ID

To get your user ID, you just need to :
send a message to your Bot from your Telegram client
call the following URL from any web browser
URL https://api.telegram.org/bot123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz/getUpdates
Answer {"ok":true,"result":[{"update_id":563273027,"message":{"message_id":505, "from":"id":11223344, "first_name":"YourFirstName", "last_name":"YourLastName", "username":"YourUserName"},
"chat":{"id":11223344, "first_name":"YourFirstName", "last_name":"YourLastName", "username":"YourUserName", "type":"private"}, "date":1483150094, "text":"Hello bot !"}}]}

You can see here that your user ID is 11223344.
This is the client ID that Telegram Bot should use to send me a message.

1.3. Get Channel ID
If your server must notify multiple users, it should notify a channel.
First, from your Telegram client, create a channel and keep it public as you need to obtain the channel ID. Give a name @YourNewChannelName to your channel.
Next, from your Bot thread, go to the Bot parameters page. You should see that your Bot is in both Members and Administrators list.

The Bot is now ready to publish messages.

To get your channel ID, you just need to send a message to @YourNewChannelName from any web browser using your Bot API key :
URL https://api.telegram.org/bot123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz/sendMessage?chat_id=@YourNewChannelName&text=FirstMessage
Answer 
{"ok":true, "result":{"message_id":2, "chat":{"id":-1234567890123, "title":"Your Channel", "username":"YourNewChannelName", "type":"channel"}, "date":1483383169, "text":"FirstMessage"}} 

You can see in the resulting JSON string that your new channel ID is -1234567890123.
You can now edit your Channel and convert its type to Private.
Your Bot can still send a message to the channel using the Channel ID :
URL https://api.telegram.org/bot123456789:AABBCCDD_abcdefghijklmnopqrstuvwxyz/sendMessage?chat_id=-1234567890123&text=SecondMessage
Answer 
{"ok":true, "result":{"message_id":2, "chat":{"id":-1234567890123, "title":"Your Channel", "username":"YourNewChannelName", "type":"channel"}, "date":1483383169, "text":"SecondMessage"}}

2. Telegram Notification Script
It's now time to install and configure Telegram notification script on the server.
The script will be in charge of sending Telegram notification and can be used by any script, service, daemon, … on the server.

2.1. Functionalities
Main functionality of Telegram notification script is to … send a Telegram notification.
It allows to :
display plain text message or a file content (log, …)
display a title
display an emoji as leading icon (codes may be found in this emoji table)
add a photo or a document
select formatting style as Markdown (default) or HTML
disable message notification on the client side
select Bot to use to send the message (thru API key)
set message recipient ID

Terminal
# telegram-notify 
Tool to send a message to a Telegram User or Channel.
Message is sent from a Telegram Bot and can contain icon, text, image and/or document.
Main parameters are :
--text <text> Text of the message or file holding the text
--photo <file> Image to display
--document <file> Document to transfer
Options are :
--title <title> Title of the message (if text message)
--html Use HTML mode for text content (markdown by default)
--silent Send message in silent mode (no user notification on the client)
--user <user-id> Recipient User or Channel ID (replaces user-id= in /etc/telegram-notify.conf)
--key <api-key> API Key of your Telegram bot (replaces api-key= in /etc/telegram-notify.conf)
Optionnal icons are :
--success Add a success icon
--error Add an error icon
--question Add a question mark icon
--icon <code> Add an icon by UTF code (ex 1F355)

Here are some examples of notifications and the expected result :
Terminal
# telegram-notify --success --text "Action *sucessful* with markdown *bold* example"
# telegram-notify --error --title "Error" --text "Error message with a title"
# telegram-notify --question --title "File content display" --text "/tmp/log.txt"
# telegram-notify --icon 1F355 --text "Message with custom icon 1F355 and embedded image" --photo "/tmp/icon.png"
# telegram-notify --text "Result is available in the embedded document" --document "/tmp/result.log"


2.2. Script
Main notification script is placed under /usr/local/sbin/telegram-notify.

#!/bin/bash
# ---------------------------------------------------
# Send notification to a telegram account thru a bot account
# Configuration is stored in /etc/telegram-notify.conf
# Depends on curl 
#
# Revision history :
# 10/01/2016, V1.0 - Creation by N. Bernaerts
# 22/01/2016, V1.1 - Handle emoticons
# 06/08/2016, V1.2 - Add API key and User ID parameters
# Remove dependency to PERL
# 08/08/2016, V1.3 - Add --document, --html and --silent options
# 10/11/2016, V1.4 - Add --icon option
# 11/01/2018, V1.5 - Add possibility of piped text, idea from Yasir Atabani
# 19/05/2018, V1.6 - Add socks5 proxy option, idea from RangerRU
# 28/06/2018, V1.7 - Add --warning and --config options, idea from Markus Hof
# ---------------------------------------------------

# initialise variables
NOTIFY_TEXT=""
DISPLAY_TEXT=""
DISPLAY_PICT=""
DISPLAY_ICON=""
DISPLAY_MODE="markdown"
DISPLAY_SILENT="false"

# Configuration file
FILE_CONF="/etc/telegram-notify.conf"

# -------------------------------------------------------
# Check tools availability
# -------------------------------------------------------

command -v curl >/dev/null 2>&1 || { echo "[Error] Please install curl"; exit 1; }
# -------------------------------------------------------
# Loop to load arguments
# -------------------------------------------------------

# if no argument, display help
if [ $# -eq 0 ] 
then
echo "Tool to send a message to a Telegram User or Channel."
echo "Message is sent from a Telegram Bot and can contain icon, text, image and/or document."
echo "Main parameters are :"
echo " --text <text> Text of the message or file with the text (use - for piped text)"
echo " --photo <file> Image to display"
echo " --document <file> Document to transfer"
echo "Options are :"
echo " --title <title> Title of the message (if text message)"
echo " --html Use HTML mode for text content (markdown by default)"
echo " --silent Send message in silent mode (no user notification on the client)"
echo " --config <file> use alternate config file, instead of default ${FILE_CONF}"
echo " --user <user-id> Recipient User or Channel ID (replaces user-id= in ${FILE_CONF})"
echo " --key <api-key> API Key of your Telegram bot (replaces api-key= in ${FILE_CONF})"
echo "Optionnal icons are :"
echo " --success Add a success icon"
echo " --warning Add a warning icon"
echo " --error Add an error icon"
echo " --question Add a question mark icon"
echo " --icon <code> Add an icon by UTF code (ex 1F355)"
echo "Here is an example of piped text :"
echo " echo 'text to be displayed' | telegram-notify --success --text -"
exit
fi


# loop to retrieve arguments
while test $# -gt 0
do
case "$1" in
"--text") shift; DISPLAY_TEXT="$1"; shift; ;;
"--photo") shift; PICTURE="$1"; shift; ;;
"--document") shift; DOCUMENT="$1"; shift; ;;
"--title") shift; DISPLAY_TITLE="$1"; shift; ;;
"--html") DISPLAY_MODE="html"; shift; ;;
"--silent") DISPLAY_SILENT="true"; shift; ;;
"--config") shift; FILE_CONF="$1"; shift; ;;
"--user") shift; USER_ID="$1"; shift; ;;
"--key") shift; API_KEY="$1"; shift; ;;
"--success") DISPLAY_ICON=$(echo -e "\U2705"); shift; ;;
"--warning") DISPLAY_ICON=$(echo -e "\U26A0"); shift; ;;
"--error") DISPLAY_ICON=$(echo -e "\U1F6A8"); shift; ;;
"--question") DISPLAY_ICON=$(echo -e "\U2753"); shift; ;;
"--icon") shift; DISPLAY_ICON=$(echo -e "\U$1"); shift; ;;
*) shift; ;;
esac
done


# -------------------------------------------------------
# Read configuration
# -------------------------------------------------------


# if configuration file is present
if [ -f "${FILE_CONF}" ]
then
# display
echo "[Info] Using configuration file ${FILE_CONF}"


# if needed, load from configuration file
[ "${API_KEY}" = "" ] && API_KEY=$(cat "${FILE_CONF}" | grep "api-key=" | cut -d'=' -f2)
[ "${USER_ID}" = "" ] && USER_ID=$(cat "${FILE_CONF}" | grep "user-id=" | cut -d'=' -f2)


# load socks proxy from configuration file
SOCKS_PROXY=$(cat "${FILE_CONF}" | grep "socks-proxy=" | cut -d'=' -f2)
else
# display
echo "[Warning] Configuration file missing ${FILE_CONF}"
fi


# check API key and User ID
[ "${API_KEY}" = "" ] && { echo "[Error] Please provide API key or set it in ${FILE_CONF}"; exit 1; }
[ "${USER_ID}" = "" ] && { echo "[Error] Please provide User ID or set it in ${FILE_CONF}"; exit 1; }


# -------------------------------------------------------
# Check for file existence
# -------------------------------------------------------

# if picture, check for image file
[ "${PICTURE}" != "" -a ! -f "${PICTURE}" ] && { echo "[error] Image file ${PICTURE} doesn't exist"; exit 1; }

# if document, check for document file
[ "${DOCUMENT}" != "" -a ! -f "${DOCUMENT}" ] && { echo "[error] Document file ${DOCUMENT} doesn't exist"; exit 1; }

# -------------------------------------------------------
# String preparation : space and line break
# -------------------------------------------------------

# if text is to be read from pipe, get it
[ ! -t 0 -a "${DISPLAY_TEXT}" = "-" ] && DISPLAY_TEXT=$(cat)

# if text is a file, get its content
[ -f "${DISPLAY_TEXT}" ] && DISPLAY_TEXT=$(cat "${DISPLAY_TEXT}")

# convert \n to LF
DISPLAY_TEXT=$(echo "${DISPLAY_TEXT}" | sed 's:\\n:\n:g')

# if icon defined, include ahead of notification
[ "${DISPLAY_ICON}" != "" ] && NOTIFY_TEXT="${DISPLAY_ICON} "

# if title defined, add it with line break
if [ "${DISPLAY_TITLE}" != "" ]
then
# convert title according to Markdown or HTML
[ "${DISPLAY_MODE}" = "html" ] && NOTIFY_TEXT="${NOTIFY_TEXT}<b>${DISPLAY_TITLE}</b>%0A%0A" \
|| NOTIFY_TEXT="${NOTIFY_TEXT}*${DISPLAY_TITLE}*%0A%0A"
fi

# if text defined, replace \n by HTML line break
[ "${DISPLAY_TEXT}" != "" ] && NOTIFY_TEXT="${NOTIFY_TEXT}${DISPLAY_TEXT}"

# -------------------------------------------------------
# Notification
# -------------------------------------------------------

# default option
ARR_OPTIONS=( "--silent" "--insecure" )

# if needed, socks5 option
[ "${SOCKS_PROXY}" != "" ] && ARR_OPTIONS=( "${ARR_OPTIONS[@]}" "--socks5-hostname" "${SOCKS_PROXY}" )

# if photo defined, display it with icon and caption
if [ "${PICTURE}" != "" ]
then
# display image
CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --form chat_id=${USER_ID} --form disable_notification=${DISPLAY_SILENT} --form photo="@${PICTURE}" --form caption="${NOTIFY_TEXT}" "https://api.telegram.org/bot${API_KEY}/sendPhoto")

# if document defined, send it with icon and caption
elif [ "${DOCUMENT}" != "" ]
then
# transfer document
CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --form chat_id=${USER_ID} --form disable_notification=${DISPLAY_SILENT} --form document="@${DOCUMENT}" --form caption="${NOTIFY_TEXT}" "https://api.telegram.org/bot${API_KEY}/sendDocument")

# else, if text is defined, display it with icon and title
elif [ "${NOTIFY_TEXT}" != "" ]
then
# display text message
CURL_RESULT=$(curl "${ARR_OPTIONS[@]}" --data chat_id="${USER_ID}" --data "disable_notification=${DISPLAY_SILENT}" --data "parse_mode=${DISPLAY_MODE}" --data "text=${NOTIFY_TEXT}" "https://api.telegram.org/bot${API_KEY}/sendMessage")

# else, nothing, error
else
# error message
echo "[Error] Nothing to notify"
exit 1
fi
# check curl request result
echo ${CURL_RESULT} | grep '"ok":true' > /dev/null || { echo ${CURL_RESULT}; exit 1; }
# end
exit 0

2.3. Configuration
Telegram notification script is using 2 default parameters that should be configured in /etc/telegram-notify.conf :
api-key : Your Bot API key
user-id : Default User ID or Channel ID to send messages to

# -------------------------------#
# /etc/telegram-notify.conf #
# -------------------------------#

[general]
api-key=YourAPIKey
user-id=YourUserOrChannelID

[network]
socks-proxy=

When calling the notification script these default parameters may be surcharged with --user and --key parameters.
2.4. Installation

Installation of Telegram notification script is quite simple as all files are available from my Debian GitHub repository :

Terminal
# wget https://raw.githubusercontent.com/NicolasBernaerts/debian-scripts/master/telegram/telegram-notify-install.sh
# ./telegram-notify-install.sh

Once you've configured /etc/telegram-notify.conf, you are ready to send your first Telegram notification from command line.

Hope it helps.
    Blogger Comment
    Facebook Comment