Enviar notificações do Bacula via Whatsapp

Existem diversos tutoriais na internet para mandar notificações de eventos do Zabbix via Whatsapp, então pensei porque não adaptar para enviar notificações do Bacula. Para realizar o envio de mensagens via whatsapp, é utilizado uma API chamada Yowsup.

Yowsup é uma biblioteca python que permite construir aplicações que utilizam os serviços do WhatsApp. Yowsup tem sido usado para criar um cliente WhatsApp não oficial para o Nokia N9 através do projeto Wazapp que estava em uso por mais de 200 mill usuários, bem como um outro cliente não oficial com todos os recursos para Blackberry 10.

https://github.com/tgalal/yowsup

Dependências necessárias baixar com o 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

 Dependências necessárias baixar com o pip:

(Pip é um gerenciador de pacotes para python)

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

Após baixar as dependências é preciso criar um arquivo de configuração em /etc/whatsapp.conf com o seguinte contéudo:

cc=55
phone=55ddxxxxxxxxx
id=Whatsapp Message
password=
cc=55
phone=número do celular com DDD. Exemplo 55 (47)1234-5678 = 554712345678
id=qualquer string ou o mesmo número do phone
password=deixar branco, pois ainda é preciso descobrir este campo.

Registrando-se no Whatsapp para envio pelo Yowsup

Neste exemplo estou utilizando um Debian 8.2 64 bits.
Atenção: é preciso de um número exclusivo para este fim, pois se você utilizar o seu próprio número, ele poderá ser bloqueado pelo motivo de estar sendo utilizado em dois aparelhos ao mesmo tempo.

# 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

Após executar o comando acima você vai receber em alguns minutos um SMS com o código de ativação, que geralmente é composto de 6 caracteres.
Substituir no comando abaixo o código recebido por SMS.

# yowsup-cli registration --register XXX-XXX --config /etc/whatsapp.conf
# Resultado do comando
INFO:yowsup.common.http.warequest:{"status":"ok","login":"55XXXXXXXXXX","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: 55XXXXXXXXXX
type: new

Pegar o valor obtido no campo pw e incluir no arquivo /etc/whatsapp.conf no campo password. Com isso já é possível enviar mensagens usando o youwsup.

Para testar o envio das mensagens vamos utilizar o seguinte comando:

yowsup-cli demos --config /etc/whatsapp.conf --send 55dddfone "teste mensagem whatsapp"

Para enviar mensagens para um grupo, o processo é um pouco diferente, é preciso criar um novo grupo ou utilizar um já existente e adicionar no grupo o número que será utilizado para enviar as mensagens.

Para descobrir o número do grupo, digite o seguinte comando no terminal, e mande uma mensagem no grupo:

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

Após mandar a mensagem no grupo o resultado do comando será algo conforme abaixo:

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

Teste
HEX:5465737465

O número do grupo é o valor que está no campo from: 55XXXXXXXXXX-YYYYYYYYYY@g.us.
No script substitua o NUM_DEST=”55DDDFONE” por NUM_DEST=”55XXXXXXXXXX-YYYYYYYYYY@g.us”

Criar o script em /etc/bacula/scripts/_send_whatsapp.sh e dar permissão a+x.
(Para que os emojis funcionem corretamente é necessário que o arquivo esteja com a codificação UTF8)

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

# Função para converter bytes para 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

# Declaração de variáveis
HOUR=$(date +%d/%m/%Y %H:%M:%S)
NUM_DEST="55DDDFONE"  # ou número do grupo
YOWSEXEC="/usr/local/bin/yowsup-cli"
CONF="/etc/whatsapp.conf"
LOG="/etc/bacula/log/whatsapp.log"
DBUSER="bacula"
DBPASSWORD="bacula"
DBNAME="bacula"

# Query para buscar as informações pelo 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"

# Atribuição de Variáveis
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 diferente caso tenha erro
# Se estiver aparecendo algum link abaixo na visualização, pressione CTRL+F5 
# para atualizar a página e mostrar corretamente.
if [ "$JobStatus" == "T" ] ; then
   HEADER=">>>>> ? BACULA BAKUP <img draggable="false" class="emoji" alt="✅" src="https://s.w.org/images/core/emoji/72x72/2705.png"> <<<<<n"  # OK
else
   HEADER=">>>>> ? BACULA BAKUP <img draggable="false" class="emoji" alt="❌" src="https://s.w.org/images/core/emoji/72x72/274c.png"> <<<<<n"  # Error
fi

# Formata a mensagem
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 múltiplas tentativas
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 $NUM_DEST "`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

Configurando o Bacula

É possível configurar em apenas em alguns Jobs, mas como eu queria em todos, configurei no JobDefs. Deve-se incluir o RunScript, conforme abaixo, salvar e dar um reload no 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
  }
}
#############################

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

Disponível em: pt-brPortuguêsenEnglish (Inglês)

Deixe uma resposta