Sending Bacula notifications using Whatsapp

There are many tutorials on the Internet to send event notifications from Zabbix by Whatsapp, so I thought why not adapt to send Bacula notifications. To perform sending messages by Whatsapp, it is used an API called Yowsup.

Yowsup is a python library that enables you build application which use WhatsApp service. Yowsup has been used to create an unofficial WhatsApp client Nokia N9 through the Wazapp project which was in use by 200K + users as well as another fully featured unofficial client for Blackberry 10

https://github.com/tgalal/yowsup

Required dependencies to install using apt-get

apt-get install python-dateutil python-protobuf python-pycryptopp python-argparse python-dev libncurses5-dev python-pip libjpeg62 libjpeg-dev python-imaging python-pillow

Required dependencies to install using pip

(Pip is a package management system used to install and manage software packages written in Python)

pip install python-axolotl-curve25519 pyreadline pillow yowsup2 --upgrade

After installing the dependencies you need to create a text file in /etc/whatsapp.conf with the following content:

#############################
cc=1 # country code
phone=1XXXXXXXXXXXX #country code + netwok area + number
id=Whatsapp Message
password=
#############################
cc = country code
phone = country code + network area + number 
id = any string or name or phone number
password = keep empty

 Requesting a registration code

Please note: You need a unique number for this purpose, because if you use your own number, it can be blocked by reason of being used in two devices at the same time.

#############################
# yowsup-cli registration --requestcode sms --config /etc/whatsapp.conf
# Resultado do comando:
INFO:yowsup.common.http.warequest:{"status":"sent","length":6,"method":"sms","retry_after":424,"sms_wait":424,"voice_wait":64}
status: sent
retry_after: 424
length: 6
method: sms
#############################

Registering on WhatsApp

After running the above command you should receive in a few minutes an SMS with the activation code, which is usually composed of 6 characters.

Replace the command below the code you received via SMS

#############################
# yowsup-cli registration --register XXX-XXX --config /etc/whatsapp.conf
# Command output
INFO:yowsup.common.http.warequest:{"status":"ok","login":"1XXXXXXXXXX","pw":"XXXXXXXXXXXXXXXXXXXXXXXXXXXX","type":"new","expiration":1484219934,"kind":"free","price":"US$0.99","cost":"0.99","currency":"USD","price_expiration":1455849712}
status: ok
kind: free
pw: XXXXXXXXXXXXXXXXXXXXXXXXXXXX
price: US$0.99
price_expiration: 1455849712
currency: USD
cost: 0.99
expiration: 1484219934
login: 1XXXXXXXXXX
type: new
#############################

Get the value obtained in the field pw and include in /etc/whatsapp.conf file in the password field. Now, it is already possible to send messages using youwsup.

Sending a whatsapp message

yowsup-cli demos --config /etc/whatsapp.conf --send 1XXXXXXXXXXdddfone "whatsapp message"

For sending to a whatsapp group, the process is a kind different.
Is necessary create a new group or use an existing one and add the in group, the number that will be used to send the messages.

To find the group number, type the following command in the terminal, and send a message in the group:

yowsup-cli demos --config /etc/whatsapp.conf --echo -d

After sending the message in the group the output of the command will look as follows:

 

DEBUG:yowsup.layers.logger.layer:rx:

<message participant="1XXXXXXXXXX@s.whatsapp.net" notify="Wanderlei" from="1XXXXXXXXXX-YYYYYYYYYY@g.us" type="text" id="B24FA2E8747BE2E3C8EFBDA4C6EF2F" t="1455910903">
<body>
Teste
HEX:5465737465
</body>
</message>
#############################

The group number is the value in the field from: 1XXXXXXXXXX-YYYYYYYYYY@g.us.
In the script replace the RECIPIENT_NUMBER = “XXXXXXXXXXX” by RECIPIENT_NUMBER = “1XXXXXXXXXX-YYYYYYYYYY@g.us”

Create an script file /etc/bacula/scripts/_send_whatsapp.sh and give permission a+x.
(For the Emoji works properly it is necessary that the file is in UTF8 encoding)

######################################################################################
#!/bin/bash
# /etc/bacula/scripts/_send_whatsapp.sh

# function bytes to humanreadable
b2h(){
    SLIST=" bytes, KB, MB, GB, TB, PB, EB, ZB, YB"
    POWER=1
    VAL=$( echo "scale=2; $1 / 1" | bc)
    VINT=$( echo $VAL / 1024 | bc )
    while [ ! $VINT = "0" ]
    do
        let POWER=POWER+1
        VAL=$( echo "scale=2; $VAL / 1024" | bc)
        VINT=$( echo $VAL / 1024 | bc )
    done
    echo $VAL$( echo $SLIST  | cut -f$POWER -d, )
}
# fim da funcao

# Variables
HOUR=$(date +%d/%m/%Y %H:%M:%S)
RECIPIENT_NUMBER="1XXXXXXXXXX"  # or group number
YOWSEXEC="/usr/local/bin/yowsup-cli"
CONF="/etc/whatsapp.conf"
LOG="/etc/bacula/log/whatsapp.log"

# MySQL config
DBUSER="bacula"
DBPASSWORD="bacula"
DBNAME="bacula"

# Query to get Jobs from JobId
sql_query="select Job.Name, Job.JobId,(select Client.Name from Client where Client.ClientId = Job.ClientId) as Client, Job.JobBytes, Job.JobFiles,
case when Job.Level = 'F' then 'Full' when Job.Level = 'I' then 'Incremental' when Job.Level = 'D' then 'Differential' end as Level,
(select Pool.Name from Pool where Pool.PoolId = Job.PoolId) as Pool,
(select Storage.Name  from JobMedia left join Media on (Media.MediaId = JobMedia.MediaId) left join Storage on (Media.StorageId = Storage.StorageId)
where JobMedia.JobId = Job.JobId limit 1 ) as Storage, date_format( Job.StartTime , '%d/%m/%Y %H:%i:%s' ) as StartTime, date_format( Job.EndTime , '%d/%m/%Y %H:%i:%s' ) as EndTime,
sec_to_time(TIMESTAMPDIFF(SECOND,Job.StartTime,Job.EndTime)) as Duration, Job.JobStatus, 
(select Status.JobStatusLong from Status where Job.JobStatus = Status.JobStatus) as JobStatusLong
from Job where Job.JobId=$1"

# Variables get the fields
str=`echo -e "$sql_query" | mysql -u $DBUSER-p$DBPASSWORD -D $DBNAME -B |  while read; do sed 's/t/|/g'; done`
JobName=`echo $str | cut -d"|" -f1`
JobId=`echo $str | cut -d"|" -f2`
Client=`echo $str | cut -d"|" -f3`
JobBytes=`b2h $(echo $str | cut -d"|" -f4)`
JobFiles=`echo $str | cut -d"|" -f5`
Level=`echo $str | cut -d"|" -f6`
Pool=`echo $str | cut -d"|" -f7`
Storage=`echo $str | cut -d"|" -f8`
StartTime=`echo $str | cut -d"|" -f9`
EndTime=`echo $str | cut -d"|" -f10`
Duration=`echo $str | cut -d"|" -f11`
JobStatus=`echo $str | cut -d"|" -f12`
Status=`echo $str | cut -d"|" -f13`

# Emojis
# OK
# http://emojipedia.org/white-heavy-check-mark/
# Not OK
# http://emojipedia.org/cross-mark/

# Header different in error status
if [ "$JobStatus" == "T" ] ; then
   HEADER=">>>>> ? BACULA BAKUP ✅ <<<<<n"  # OK
else
   HEADER=">>>>> ? BACULA BAKUP ❌ <<<<<n"  # Error
fi
# Message format
MESSAGE="$HEADERnJobName=$JobNamenJobid=$JobIdnClient=$ClientnJobBytes=$JobBytesnJobFiles=$JobFilesnLevel=$LevelnPool=$PoolnStorage=$StoragenStartTime=$StartTimenEndTime=$EndTimenDuration=$DurationnJobStatus=$JobStatusnStatus=$StatusnAttempt="
MESSAGELOG="Message: JobName=$JobName | Jobid=$JobId | Client=$Client | JobBytes=$JobBytes | Level=$Level | Status=$Status"

# Loop to try until message sent correctly
COUNT=1
while [ $COUNT -le 20 ]; do

   echo "$(date +%d/%m/%Y %H:%M:%S) - Start message send (attempt $COUNT) ..." >> $LOG
   echo "$(date +%d/%m/%Y %H:%M:%S) - $MESSAGELOG" >> $LOG

   while [ $(ps -ef | grep yowsup | grep -v grep | wc -l) -eq 1 ]; do
      echo "$(date +%d/%m/%Y %H:%M:%S) - Yowsup still running, waiting 2 seconds before a new try ..." >> $LOG
      sleep 2; 
   done;

   $YOWSEXEC demos --config $CONF --send $RECIPIENT_NUMBER "`echo -e "$MESSAGE${COUNT}"`" &>> $LOG
   RET=$?

   if [ $RET -eq 0 ]; then
     echo "$(date +%d/%m/%Y %H:%M:%S) - Attempt $COUNT executed successfully!" >> $LOG 
     exit 0
   else
     echo "$(date +%d/%m/%Y %H:%M:%S) - Attempt $COUNT failed!" >> $LOG 
     echo "$(date +%d/%m/%Y %H:%M:%S) - Waiting 30 seconds before retry ..." >> $LOG
     sleep 30
     (( COUNT++ ))
   fi

done
######################################################################################

Change Bacula Config

You can set in a few some Jobs, but how I wanted in all, I set up in JobDefs. It should include the RunScript, as indicated below, save and do reload in bconsole:

JobDefs {
 Name = "DefaultJob"
 Type = Backup
 Level = Incremental
 Client = bacula-fd
 FileSet = "FileSetBacula"
 Schedule = "WeeklyCycle"
 Messages = Standard
 Pool = "File"
 SpoolAttributes = yes
 Priority = 10
 Write Bootstrap = "/etc/bacula/working/%c.bsr"
 RunScript {
  Command = "/etc/bacula/scripts/_send_whatsapp.sh %i"
  RunsWhen = After
  RunsOnFailure = yes
  RunsOnClient = no
  RunsOnSuccess = yes # execute in all jobs
 }
}

Source: http://www.huttel.com.br/

Disponível em: enEnglish

Leave a Reply