Sviluppo di un bot Telegram per la visualizzazione di dati aziendali

Pagina creata da Pietro Masi
 
CONTINUA A LEGGERE
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Università degli Studi di Padova
                Dipartimento di Matematica "Tullio Levi-Civita"
                        Corso di Laurea in Informatica

              Sviluppo di un bot Telegram per la
                visualizzazione di dati aziendali
                              Tesi di laurea triennale

Laureando :                                                          Relatore :
Marco Giorgio                                               Prof. Gilberto Filè

                           Anno Accademico 2016/2017
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Sommario

Questo documento descrive l'esperienza di stage curricolare svolta dal 3 Luglio 2017 al
10 Settembre 2017, presso l'azienda Miriade, con sede a Thiene (VI).
Il documento ha lo scopo di:
   • illustrare il contesto aziendale nel quale il laureando è stato inserito;

   • descrivere il progetto di stage;

   • riportare le attività svolte durante lo stage;
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Ringraziamenti

Desidero ringraziare con aetto la mia famiglia, che mi ha supportato e sopportato nei
momenti di dicoltà
Sono grato a tutti i colleghi di Miriade, per avermi aiutato a portare a termine questo
progetto. Un pensiero speciale va al mio amico Riccardo, il cui aiuto è stato determinante
per raggiungere questo traguardo.

                                                                           Marco Giorgio
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Indice

1 Analisi del contesto aziendale                                                                                                         1
  1.1 Miriade e il suo ambito di attività .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
  1.2 Organizzazione aziendale . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
      1.2.1 Struttura . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    1
      1.2.2 Comunicazione . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    2
  1.3 Sviluppo software . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    2
      1.3.1 Metodo di lavoro . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    2
2 Presentazione dello stage                                                                                                             3
  2.1 Descrizione del progetto di stage . . . . . . . . . . . . . . . . . . . . . . .                                                   3
      2.1.1 Prodotti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                                  3
      2.1.2 Tecnologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                                  7
3 Svolgimento dello stage                                                                                                               11
  3.1 Metodo di lavoro . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
  3.2 Attività preliminari . . . . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
      3.2.1 Preparazione dell'ambiente di lavoro                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   11
      3.2.2 Studio individuale . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
  3.3 Sviluppo del bot . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
      3.3.1 Analisi dei requisiti . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   16
      3.3.2 Progettazione . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
      3.3.3 Implementazione . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   20
  3.4 Analisi dei principali problemi . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
      3.4.1 Utilizzo di Spring . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
      3.4.2 Utilizzo di pgAdminIII . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
      3.4.3 Metodo agile . . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   42
4 Conclusioni                                                                                                                           43
  4.1 Obiettivi raggiunti . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
      4.1.1 Funzionalità del bot . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
      4.1.2 Formazione . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
  4.2 Considerazioni sull'esperienza di stage . . . . . .                       .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
      4.2.1 Motivazioni per cui ho intrapreso lo stage                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   44

                                            I
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
4.2.2 Aspettative . . . . . . . .    .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
      4.2.3 Obiettivi dello stage . . .    .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
      4.2.4 Aspettative soddisfatte . .    .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
      4.2.5 Valore dello stage . . . . .   .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   46
  4.3 Considerazioni sul corso di laurea   .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   46
Glossario                                                                                                                               47
Sitograa                                                                                                                               50

                                           II
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
Elenco delle gure
 1.1 Logo di Miriade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                              1
 2.1    Esempio di tastiera . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 4
 2.2    Esempio di tastiera inline . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 5
 2.3    Esempio indicatore/ltri . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 6
 2.4    Esempio visualizzazione con graco . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 7
 2.5    Logo Telegram . . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 7
 2.6    Logo Google Cloud Speech . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 8
 2.7    Logo Google Cloud Natural Language          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 9
 2.8    Logo Spring . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 9
 2.9    Architettura Spring . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . 10
 3.1    Logo Linux Mint . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   11
 3.2    Logo IntelliJ IDEA . . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   12
 3.3    Logo Git . . . . . . . . . . . . . . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   12
 3.4    Logo PostgreSQL . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   13
 3.5    Logo Highcharts . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   13
 3.6    Esempio graco di output . . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   18
 3.7    Conversazione relativa al fatturato. . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   21
 3.8    Conversazione relativa al margine. . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   21
 3.9    JSON di input servizio Speech-to-text . . . . . . . .                       .   .   .   .   .   .   .   .   .   .   .   .   23
 3.10   Dettaglio "cong" JSON di congurazione . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   24
 3.11   Dettaglio "audio" JSON di congurazione . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   25
 3.12   JSON di risposta . . . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   26
 3.13   JSON di input Natural Language API . . . . . . . .                          .   .   .   .   .   .   .   .   .   .   .   .   27
 3.14   JSON di risposta Natural Language API . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   28
 3.15   Esempio di dependency tree . . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   28
 3.16   Database Access Object Pattern . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   30
 3.17   Tabella contenente le conversazioni . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   30
 3.18   Schermata iniziale con generazione dinamica tastiera                        .   .   .   .   .   .   .   .   .   .   .   .   36
 3.19   Output stato iniziale Fatturato . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   37
 3.20   Output testuale . . . . . . . . . . . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   38
 3.21   Output graco . . . . . . . . . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   39
 3.22   Elaborazione messaggio vocale . . . . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   40

                                            III
Sviluppo di un bot Telegram per la visualizzazione di dati aziendali
3.23 Funzionalità "Come va oggi?" . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.24 Crash pgAdminIII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

                                       IV
Capitolo 1

Analisi del contesto aziendale

1.1       Miriade e il suo ambito di attività

Miriade è una piccola azienda con sede a Thiene e Padova. Essa ore servizi di consu-
lenza informatica di vario tipo (sistemistico, di sviluppo, amministrazione di database e
business intelligence).

                                 Figura 1.1: Logo di Miriade1

1.2       Organizzazione aziendale

1.2.1      Struttura

L'azienda è suddivisa in tre macro unità:
      • Area amministrativa: Gestione degli aspetti economici e nanziari.

      • Area commerciale: Si occupa di pianicare le strategie di mercato, di vendere il
        prodotto e di assistere i clienti.
  1
      Fonte immagine http://www.miriade.it

                                              1
• Area ricerca e sviluppo: Si occupa di creare e migliorare il prodotto.

   A sua volta l'Area ricerca e sviluppo si articola in:
   • Area sistemi: Si occupa di ideare soluzioni riguardanti l'ambito sistemistico
      (gestione server, migrazioni, congurazione di software aziendali.
   • Area sviluppo: Si occupa della progettazione e dello sviluppo dei prodotti soft-
      ware.
   • Area database: Si occupa della creazione e gestione dei database.

   • Area business intelligence: Si occupa di progettare soluzioni per organizzare e
      rielaborare le informazioni di un'azienda.

1.2.2   Comunicazione

La comunicazione tra colleghi avviene prevalentemente a voce, in modo diretto. Tutta-
via capita spesso che alcune gure professionali, soprattutto per quanto riguarda l'area
sistemi, siano in trasferta. Per ovviare a questo problema si utilizzano spesso Hangouts
e Gmail, poiché ogni dipendente ha un account aziendale su piattaforma Google.

1.3     Sviluppo software

1.3.1   Metodo di lavoro

Il modello di sviluppo software adottato dall'azienda segue la metodologia agile. Il re-
sponsabile d'area assegna dei task agli sviluppatori, che devono essere portati a termine
entro la ne dello sprint. Settimanalmente viene eettuato uno scrum tra tutti i membri
del team di sviluppo.

                                            2
Capitolo 2

Presentazione dello stage

2.1     Descrizione del progetto di stage

2.1.1    Prodotti

AsOneBot
Ad un'azienda sono associati una serie di indicatori economici, che ne descrivono il be-
nessere. Normalmente si accede a questi dati mediante strumenti di business intelligence
che permettono ad un manager di monitorare la situazione aziendale e pianicare le azio-
ni successive. Miriade utilizza a questo scopo un'applicazione web, il cui limite risulta
essere la non portabilità, poiché la sua interfaccia non è ottimizzata per la fruizione su
smartphone e tablet. L'obiettivo dello stage era quello di realizzare uno strumento che
permettesse la consultazione degli stessi dati ottenuti dal servizio di business intelligence,
che potesse essere consultato in mobilità.
La prima soluzione considerata era quella di interfacciarsi direttamente allo strumento
di business intelligence, ma questa strada è stata scartata poiché le API oerte non lo
consentivano, oltre al fatto che la documentazione messa a disposizione era molto sca-
dente. Si è pensato quindi di memorizzare i dati di interesse in un database realizzato
appositamente, in modo che qualsiasi applicazione potesse reperire le informazioni con
facilità.
Avendo un database dedicato, sono state individuate almeno tre soluzioni per risolvere il
problema:
   • Sviluppo di un'applicazione nativa per smartphone.

   • Sviluppo di un sito mobile-friendly.

   • Sviluppo di un bot Telegram.
    Se si fosse realizzata un'app per smartphone, sarebbe stato necessario sviluppare due
distinte applicazioni, una per sistema operativo Android e una per iOS. Lo sviluppo
di un sito web avrebbe permesso di evitare questo problema, tuttavia ci sarebbe stata
comunque la necessità di sviluppare sia il front-end che il back-end. La creazione di un

                                              3
bot Telegram, invece, avrebbe consentito di realizzare solamente il back-end. Un bot
è infatti un'applicazione eseguita all'interno del client di messaggistica di Telegram, a
cui l'utente può inviare comandi mediante l'interfaccia di chat messa a disposizione dal
client. I comandi vengono inviati al bot sia scrivendo dei messaggi, come se fosse una
conversazione con un'altra persona, sia mediante apposite tastiere:

   • Tastiera normale

   • Tastiera inline

    La tastiera normale si presenta come una serie di pulsanti cliccabili che compaiono
nella metà inferiore della nestra di chat. Quando si preme un bottone, viene inviato al
bot il messaggio presente sopra di esso.

                            Figura 2.1: Esempio di tastiera

    La tastiera inline invece, permette di allegare dei pulsanti direttamente ad un mes-
saggio, e la pressione di uno di essi causa una callbackQuery, un input personalizzabile
dallo sviluppatore.

                                           4
Figura 2.2: Esempio di tastiera inline

    L'interazione dell'utente con il bot usando i meccanismi descritti è veloce ed intuitiva,
ciò permette di ottenere informazioni in modo rapido ed in mobilità, il tutto senza la
necessità di sviluppare un'interfaccia di front-end. Per questi motivi l'implementazione
di un bot Telegram è risultata essere la soluzione migliore tra quelle elencate.

    Nell'ambito di interesse, un comando accettato dal bot può rappresentare due cose
distinte:
   • L'indicatore economico di cui si vogliono conoscere i dettagli.

   • I ltri da usare per aggregare i dati dell'indicatore economico scelto (periodo
      temporale, output testuale o graco...).
Si è pensato quindi di utilizzare la tastiera normale per elencare gli indicatori e la tastiera
inline per specicare i ltri. Prendiamo ad esempio l'indicatore economico del fatturato.
A questo possono essere applicati diversi ltri, come il fatturato aggiornato alla data
corrente, oppure quello per mese o la sua incidenza. La gura che segue rappresenta il
risultato voluto considerando l'esempio del fatturato.

                                              5
Figura 2.3: Esempio indicatore/ltri

    Per poter sostituire lo strumento di business intelligence, era importante che il bot
potesse mostrare i dati anche mediante l'uso di graci per alcuni ltri. Ad esempio,
considerando sempre l'indicatore del fatturato, si voleva dare la possibilità all'utente di
visualizzare i dati per mese mediante graco, per rendersi conto a colpo d'occhio del suo
andamento.

                                            6
Figura 2.4: Esempio visualizzazione con graco

    Inne, si voleva rendere il bot capace di ricevere ed interpretare messaggi vocali,
contenenti dei comandi espressi in linguaggio naturale. L'utente avrebbe potuto mandare
ad esempio la seguente richiesta: "Qual è il fatturato ad oggi?", e il bot avrebbe presentato
direttamente i dati richiesti senza interagire mediante la tastiera.

2.1.2    Tecnologie

Telegram

                                Figura 2.5: Logo Telegram

Telegram è un servizio di messaggistica no-prot cross-platform basato su cloud. Sono
stati sviluppati client per tutte le piattaforme maggiormente utilizzate: Android, iOS,
Windows Phone, Windows NT, macOS e Linux. Come esperienza utente si presenta

                                             7
molto simile a Whatsapp, di cui è il principale competitor. Le funzionalità distintive di
Telegram sono:
   • Multiaccesso: Telegram permette di accedere da smartphone o tablet sprovvisti
     di scheda SIM.
   • Client desktop: Telegram è dotato di un client desktop separato rispetto ai
     client mobile. Questo consente ad esempio di accedere al servizio anche avendo
     lo smartphone spento.
   • Cloud: Telegram memorizza tutte le informazioni, compresi audio, foto e allegati,
     in cloud. Ciò consente di avere la stessa esperienza d'uso su dispositivi diversi
     contemporaneamente.

Telegram Bot Java API
Le API che Telegram ore per creare i bot sono HTTP, ne esistono quindi diverse imple-
mentazioni in vari linguaggi di programmazione che ne semplicano l'utilizzo. Nel mio
progetto ho utilizzato l'implementazione Java reperibile a questo link: Telegram Bot API
Java.

Google Cloud Speech API

                        Figura 2.6: Logo Google Cloud Speech

Google Cloud Speech è un servizio di speech-to-text facente parte della suite di API
cloud messe a disposizione da Google. Supporta oltre 110 lingue e restituisce i risultati
in tempo reale grazie ad una potente rete neurale. Ci si può interfacciare al servizio
mediante chiamate REST, inviando un JSON di input contenente la codica in base
64 di un le audio. In risposta si ottiene un JSON contenente il testo riconosciuto
analizzando il le audio.

                                           8
Google Cloud Natural Language API

                   Figura 2.7: Logo Google Cloud Natural Language

Google Cloud Natural Language API è un servizio che permette di eettuare l'analisi
sintattica di una frase, estraendo da quest'ultima i token e le entità, ottenendo informa-
zioni su come i componenti della frase siano in relazione tra loro. Anche questo servizio
fa parte della suite di Google Cloud e si utilizza in modo similare al precedente. Si invia
un JSON di input contenente la frase da analizzare e si ottiene in risposta un altro JSON,
che rappresenta la frase decomposta ed analizzata.

Spring

                                 Figura 2.8: Logo Spring

Spring è un framework open source per lo sviluppo di applicazioni su piattaforma Java.
La sua architettura è modulare, per questo è possibile utilizzare solo i componenti di cui
si ha bisogno. Le parti in cui il framework è suddiviso sono quattro:
   • Core: Costituisce il nucleo del framework, sopra di esso sono sviluppati gli altri
     moduli. All'interno del core, sono implementate le funzionalità di Dependency
     injection e Inversion of control.
   • Data Access: È il modulo che fornisce funzionalità di astrazione per l'accesso ai
     dati. Ciò si traduce nella gestione di connessioni, transazioni ed eccezioni molto
     semplicata.
   • AOP: Implementa le funzionalità per la programmazione Aspect oriented.

                                            9
• Web: Permette lo sviluppo di un'applicazione Web. Particolarmente utile è l'im-
     plementazione del pattern MVC.

                           Figura 2.9: Architettura Spring

   Durante lo stage ho fatto largo uso delle funzionalità di Dependency injection e di
accesso ai dati oerti da questo framework.

                                         10
Capitolo 3

Svolgimento dello stage

3.1     Metodo di lavoro

Per l'intera durata dello stage ho seguito i principi del modello agile, comunemente usato
in azienda per lo sviluppo di prodotti. Ciò ha permesso di realizzare le prime funzionalità
del bot molto presto e mi ha invogliato sempre di più a proseguire nello sviluppo. Inoltre,
adottando questa metodologia di lavoro, ho potuto mostrare n da subito l'interazione
utente-bot al mio tutor, che ha potuto darmi un suo feedback molto velocemente.

3.2     Attività preliminari

3.2.1    Preparazione dell'ambiente di lavoro

Sistema operativo

                              Figura 3.1: Logo Linux Mint

Il primo giorno di stage è stato dedicato all'installazione e alla congurazione del sistema
operativo e dei programmi necessari per lo sviluppo del bot. Come sistema operativo ho
scelto di utilizzare Linux Mint 18.2, apprezzato per la sua stabilità. Esso è basato su
Ubuntu 16.04, una versione LTS.

                                            11
IDE

                            Figura 3.2: Logo IntelliJ IDEA

Come IDE ho deciso di utilizzare IntelliJ IDEA, ormai il nuovo punto di riferimento
per quanto riguarda Java. Ore funzionalità molto utili come il refactor del codice, la
ricerca di linee duplicate, un autocompletamento ecace e ha a disposizione un debugger
intuitivo e semplice da usare. È disponibile in due versioni, una a pagamento e una open
source e gratuita. Durante il mio stage ho usato la versione open source.

Git

                                 Figura 3.3: Logo Git

Per eettuare il versionamento del codice ho deciso di usare Git, sfruttando l'hosting
oerto dalla piattaforma GitHub. Inoltre ho installato GitKraken, un client che ore
un'interfaccia visuale per eettuare le operazioni tipiche del sistema Git.

                                          12
PostgreSQL

                              Figura 3.4: Logo PostgreSQL

In azienda è già presente un server di test con database PostgreSQL, ho deciso quindi di
sfruttare questo server per il mio bot. Come client ho usato pgAdmin III, in seguito me
ne sono pentito perché è fatto male e garantisce un'esperienza utente pessima.

Highcharts Server

                              Figura 3.5: Logo Highcharts

Per implementare la possibilità per il bot di generare graci ho utilizzato il servizio Hi-
ghcharts. Esso consente di creare moltissime tipologie di graci, riceve in input un JSON
contenente i dati ed il tipo di graco e restituisce l'immagine corrispondente.
La congurazione di un server Highcharts non è stata dicoltosa, l'unico requisito ri-
chiesto è la presenza di node.js sul pc, che è possibile installare con un solo comando
da terminale. In seguito ho seguito le istruzioni presenti a questo link per installare
Highcharts: Installazione Highcharts.

                                            13
3.2.2    Studio individuale

API Telegram
Ho dedicato la prima settimana di stage allo studio delle API di Telegram e alla creazione
di un bot associato ad un numero di telefono fornito dall'azienda. La documentazione di
queste API è molto ben fatta, metodi e tipi messi a disposizione sono ben deniti e facili
da capire.
Ho invece incontrato qualche problema nello studiare la libreria Java che implementa le
API, in quanto non segue precisamente la documentazione uciale. Ad esempio il metodo
sendMessage() non è presente ed è invece sostituito da execute(), poiché assolve anche
ad altri compiti. Inoltre la proprietà chatId che nella documentazione ha tipo Integer,
è stata implementata come Long. Sono insomma presenti alcune piccole incongruenze
che hanno rallentato lo studio.
La creazione di un bot invece è molto semplice ed avviene tramite l'interazione con un
altro bot, chiamato BotFather. Si manda a BotFather l'username del bot che si vuole
creare e viene restituito un token da inserire all'interno dell'applicazione.

Google Cloud API
Le API di Google Cloud sono ben documentate e sono semplici da usare poiché non sono
altro che chiamate HTTP di tipo POST. È possibile testarne il funzionamento diretta-
mente online, poiché Google mette a disposizione un front-end che simula la chiamata
che si fa all'interno delle applicazioni. Per avere un'idea ancora migliore sul tipo di input
accettato e l'output restituito, ho usato un'estensione di Chrome chiamata Postman, che
permette di eettuare diversi tipi di chiamate HTTP.

Spring
Per realizzare il bot, avrei potuto fare a meno di usare Spring, tuttavia le ore necessarie
per l'apprendimento di questo framework sono state ben spese. Esso consente infatti di
realizzare la Dependency injection e la connessione a diversi tipi di database in modo
estremamente semplice.
Il framework mette a disposizione l'IoC container, un contesto congurabile per la crea-
zione e risoluzione delle dipendenze di componenti che vengono chiamati bean. L'IoC
container può essere visto come un contenitore dove vengono inseriti oggetti che pos-
sono essere utilizzati ovunque nell'applicazione, poiché vengono iniettati dove servono
direttamente dal framework. Il container è realizzato per attraverso due interfacce:
   • BeanFactory: Denisce le funzionalità di base di gestione dei bean.

   • ApplicationContext: Estende le funzionalità oerte da BeanFactory aggiungen-
      do la gestione degli eventi, l'internazionalizzazione e l'integrazione con AOP.
   In particolare, l'interfaccia BeanFactory si occupa di:
   • creare i bean necessari all'applicazione.

                                             14
• inizializzare le loro dipendenze attraverso l'utilizzo dell'injection.

    • gestirne l'intero ciclo di vita.

     Per svolgere tali mansioni, il container necessita di congurazioni impostate dallo
sviluppatore che specicano i bean che dovranno essere gestiti e le loro dipendenze. In
passato, per descrivere una congurazione, si usavano le XML. Tale pratica è stata ab-
bandonata in favore dell'uso di annotation. Immaginiamo ad esempio di avere due classi
Driver e License, con Driver che necessita di un oggetto License per assolvere al suo
compito.
Per realizzare l'injection, è suciente decorare la classe License con l'annotation @Com-
ponent, che indica a Spring che tale classe deve essere un bean disponibile nel contai-
ner. Inoltre nella classe Driver, si crea un attributo ti tipo License, decorato con
l'annotation @Autowired. Ciò indica al framework che deve inizializzare l'oggetto con
l'istanza contenuta nel container.
@Component
public class License {

    private String number="123456ABC";

    @Override
    public String toString() {
       return "License [number=" + number + "]";
    }

    // getter e setter
}

                                Listing 3.1: Uso di @Component

@Component("driver")
public class Driver {

    @Autowired
    private License license ;

    // getter e setter

    @Override
    public String toString() {
       return "Driver [ license =" + license + "]";
    }
}

                                Listing 3.2: Uso di @Autowired
   All'interno del mio progetto, interrogo il database PostgreSQL piuttosto spesso,
Spring JDBC ha consentito di semplicare queste operazioni.

                                                 15
Di norma in Java si usa JDBC per eseguire operazioni su database, tuttavia questo
necessita di occuparsi di alcuni problemi:

   • Bisogna scrivere del codice prima e dopo una query, ad esempio per creare una
       connessione, chiudere un resultSet, chiudere la connessione.
   • Bisogna gestire le eccezioni.

   • Bisogna gestire le transazioni.

   Spring JDBC ore delle classi che permettono l'esecuzione diretta di query e si
occupano di risolvere i problemi descritti in modo automatico:

   •   JdbcTemplate
   •   NamedParameterJdbcTemplate
   •   SimpleJdbcTemplate
   •   SimpleJdbcInsert
   •   SimpleJdbcCall
    Durante il progetto ho fatto largo uso di JdbcTemplate e NamedParameterJdbcTem-
plate.

3.3     Sviluppo del bot

3.3.1    Analisi dei requisiti

Come descritto nel capitolo relativo alla presentazione generale dello stage, lo scopo del
bot è quello di permettere l'accesso immediato ad alcuni indicatori economici aziendali e
per ciascuno di essi, visualizzare i dati utilizzando specici ltri. Un indicatore e la lista
dei suoi ltri possono essere visti come una conversazione. Ad esempio la conversazio-
ne relativa al fatturato è composta dall'indicatore economico "fatturato" e dai ltri "ad
oggi", "per mese", "incidenza"...
È lecito pensare che ciascuna azienda voglia denire le proprie conversazioni personaliz-
zate, per questo motivo la logica del bot non deve dipendere da un set di conversazioni
predenite, ma funzionare con tutte quelle possibili. Per realizzare ciò, le conversazioni
devono risiedere su un database, e non devono essere integrate direttamente nel codice
del bot.
Un bot Telegram è di default pubblico, tutti possono accedervi conoscendo l'username.
Per la natura del bot oggetto dello stage, è necessario implementare un meccanismo di
permessi, memorizzati su database, che consenta di accedere al bot ai soli utenti auto-
rizzati.
Per evitare di inserire manualmente nel database conversazioni e permessi, un obiettivo

                                             16
facoltativo prevede l'implementazione di un modo per importare questi dati da spread-
sheet presenti su Google Drive nel database in modo automatico.
Un altro obiettivo facoltativo consiste nel memorizzare i dati relativi ai vari indicatori
economici non su database locale, ma in cloud, in particolare usando i database distribuiti
messi a disposizione da Google, che è possibile interrogare mediante il servizio BigQuery.
Di seguito si specica l'elenco dei requisiti:
   • Obbligatori

         Implementazione di un bot Telegram che permette l'accesso agli indicato-
          ri economici fatturato e margine, mediante l'uso delle tastiere messe a
          disposizione da Telegram.
         Implementazione di un modo per separare la logica del bot dalle conversazioni,
          rendendolo utilizzabile per tutte le aziende.
         Implementazione di un sistema di permessi che consenta di accedere al bot
          solo agli utenti autorizzati.
   • Opzionali

         Permettere al bot di inviare i dati sotto forma di graco, dove necessario.
         Permettere al bot di ricevere in input un messaggio vocale contenente la ri-
          chiesta dell'utente, e restituire in output i dati desiderati dopo aver elaborato
          l'audio del messaggio.
         Implementazione di un modo per importare le conversazioni e i permessi da
          spreadsheet memorizzati su Google Drive, al database locale.
         Memorizzare i dati di interesse degli indicatori economici non su database
          locale, ma in cloud, usando il servizio Google BigQuery.

3.3.2    Progettazione

Struttura delle conversazioni
Ad alto livello, si voleva che il bot desse informazioni in merito a due indicatori economici
aziendali:
   • Fatturato

   • Margine
In particolare si volevano ottenere i seguenti dati:
   • Fatturato

         Fatturato ad oggi.
         Fatturato per mese.
         Incidenza del fatturato sul budget ad oggi.

                                             17
 Incidenza del fatturato sul budget per mese.
         Incidenza del fatturato rispetto all'anno precedente.
   • Margine

           Margine ad oggi.
           Margine per mese.
           Incidenza del margine consuntivo sul budget ad oggi.
           Incidenza del margine consuntivo sul budget per mese.
           Incidenza del margine rispetto all'anno precedente.
Per entrambe queste conversazioni, si voleva che il bot restituisse i dati in forma di gra-
co, qualora le informazioni richieste fossero state di cadenza mensile.
Per quanto riguarda l'output testuale, il bot doveva restituire stringhe di testo contenenti
i dati richiesti, ad esempio: "Il fatturato al 06/11/2017 è di 7922145.32 euro" rispon-
de alla richiesta di mostrare il fatturato aggiornato alla data corrente (nell'esempio il
06/11/2017).
L'output graco, invece, doveva essere simile a quello ottenuto usando lo strumento di
business intelligence. Segue l'esempio di graco che si voleva ottenere per visualizzare il
fatturato per mese.

                          Figura 3.6: Esempio graco di output

                                            18
Gestione dei permessi
Poiché i bot Telegram sono pubblici, si voleva realizzare un sistema di controllo dei per-
messi che consentisse di accedere al bot ai soli utenti autorizzati. In particolare, il bot
doveva restituire in output il messaggio: "Mi dispiace, ma non hai i permessi per accedere
a questo bot", ad ogni messaggio inviato da un utente non autorizzato.
Oltre a ciò, vi era la necessità di implementare un sistema di permessi anche per le
conversazioni. Ad esempio si voleva che la conversazione relativa al fatturato fosse acces-
sibile solo da alcuni utenti, mentre il margine fosse disponibile per tutti. Il bot si sarebbe
dovuto occupare di gestire anche queste tipologie di autorizzazioni.

Interpretazione di un messaggio vocale
Oltre all'interazione con il bot mediante tastiera, si voleva permettere all'utente di man-
dare richieste in linguaggio naturale mediante l'invio di un messaggio vocale. Ad esempio
alla richiesta: "Qual è il fatturato ad oggi?", il bot avrebbe dovuto rispondere con il
messaggio: "Il fatturato al 06/11/2017 è di 7922145.32 euro". Nello specico:
   • I messaggi non dovevano essere predeniti, ad esempio: "Qual è il fatturato ad og-
      gi?" e "Ad oggi, qual è il fatturato?" dovevano essere accettati entrambi e restituire
      lo stesso output.
   • La richiesta dell'utente doveva essere interpretata quanto più possibile. Ad esempio
      se l'utente avesse mandato il messaggio generico: "Qual è il fatturato?", il bot non
      avrebbe dovuto rispondere che non poteva accettare la richiesta, ma avrebbe dovuto
      chiedere all'utente se desiderava i dati del fatturato ad oggi o per mese.
Anche nell'interpretazione di un messaggio vocale, il bot avrebbe dovuto tenere in conto
dei permessi dell'utente di accedere solo ad alcune conversazioni.

Database cloud
Si voleva permettere ai dati di risiedere sia su database cloud che locale contemporanea-
mente, in maniera del tutto trasparente per l'utente. Ciò signica ad esempio fare in
modo che i dati della conversazione relativa al fatturato siano su database locale, e quelli
del margine in cloud. I problemi da arontare erano i seguenti:
   • Discriminare il caso in cui i dati risiedessero in locale dal cloud.

   • Restituire all'utente lo stesso output nei due casi, anche se i dati venivano reperiti
      in due modi dierenti.

                                             19
3.3.3    Implementazione

Struttura di una conversazione
All'inizio della mia esperienza di stage, mi sono stati forniti i dati che il bot avrebbe
dovuto visualizzare, essi corrispondono alle possibili richieste elencate nel capitolo 3.3.2.
Era importante quindi strutturare le richieste, in modo che potessero essere facilmente
elaborate. Inoltre vi era la necessità che il modo di rappresentare queste richieste fosse
generale, per consentire al bot di funzionare ugualmente indipendentemente dai dati da
visualizzare.
Innanzitutto ho deciso di raggruppare le richieste per conversazione, separando le richie-
ste relative al fatturato da quelle relative al margine. Successivamente ho pensato che
ogni conversazione potesse essere composta da più passi, ciascuno dei quali avrebbe per-
messo di capire meglio la richiesta nale dell'utente ltrando progressivamente i dati da
visualizzare. Ad esempio, prendendo in considerazione la seguente richiesta: "Incidenza
del fatturato sul budget ad oggi". La conversazione di riferimento è quella del fatturato,
e i passi da cui è composta sono:
   • Incidenza

   • sul budget

   • ad oggi

In questo senso, una conversazione può essere pensata come un automa a stati niti.
Lo stato iniziale indica appunto l'inizio della conversazione (fatturato o margine), e le
transizioni verso un altro stato corrispondono ai diversi passi in cui si articola la conver-
sazione, che equivalgono agli input accettati dal bot per capire la richiesta dell'utente.
Uno stato è nale quando si è capito cosa l'utente vuole sapere e si può procedere quindi
alla restituzione dei dati, in formato graco o testuale.
Segue una rappresentazione graca delle conversazioni e dei passi da cui sono composte.

                                             20
Figura 3.7: Conversazione relativa al fatturato.

Figura 3.8: Conversazione relativa al margine.

                      21
A livello di implementazione su database, ho realizzato due tabelle, una per rap-
presentare le conversazioni, e una per rappresentare gli stati, in relazione uno a molti.
Ciascuno stato è composto da un output, una serie di input accettati, e gli stati successivi
da raggiungere a seguito della ricezione dei diversi input. Utilizzando questa logica si
possono denire conversazioni personalizzate, ognuna articolata in diversi passi, anch'essi
deniti a piacimento, che il bot sarà in grado di gestire poiché la struttura di base rimane
identica.

Gestione dei permessi
Quando il bot riceve un messaggio, insieme ad esso viene trasmesso l'id univoco dell'u-
tente Telegram che lo ha mandato. È stato naturale quindi sfruttare questa informazione
per implementare la gestione dei permessi per accedere al bot. Ho creato una tabella nel
database per memorizzare gli utenti, e una tabella per i permessi (ad esempio admin,
utente base) in relazione molti-a-molti. Inoltre ho messo in relazione molti-a-molti la
tabella delle conversazioni con quella dei permessi.
In questo modo una volta che l'utente manda un messaggio al bot vengono prelevati i suoi
permessi e confrontati con quelli necessari per accedere alla conversazione desiderata. Se
il grado di autorizzazione non è suciente viene mandato all'utente un messaggio che gli
comunica che non può accedere alla conversazione.

Generazione di graci mediante Highcharts
Lo strumento di business intelligence usato dall'azienda sfrutta Highcharts per generare
graci. È stato quindi naturale usare lo stesso servizio per replicare la medesima espe-
rienza utente.
Per poter generare un graco, Highcharts necessita dei parametri del graco stesso, che
ne descrivono tipologia, colori e i dati da visualizzare. Per rendere il codice Java più
generale possibile, è bastato inserire come proprietà all'interno dello stato nale di una
conversazione che richiede un output graco, un campo dati di tipo JSON, che rappre-
senta il template del graco in cui iniettare i dati reperiti da query che mi sono state
fornite dall'azienda. Usando questo espediente, se il bot rileva che si è entrati in uno stato
che necessita di interrogare il servizio Highcharts, tutto quello che deve fare è reperire
il template del graco dal database, eseguire la query associata per ottenere i dati da
visualizzare, inserirli nel template e mandare la richiesta al server di Highcharts.

Interpretazione di un messaggio vocale
L'interpretazione di un messaggio vocale dell'utente passa attraverso due step consecutivi:
   • Estrapolazione del testo dal messaggio vocale mediante il servizio Google Speech-
      to-text
   • Interpretazione del testo mediante il servizio Google Natural language

                                             22
Ho optato per i servizi oerti da Google per la loro semplicità di utilizzo e poiché
l'azienda aveva già a disposizione degli account abilitati all'uso di queste API.
La chiamata HTTP al servizio di speech-to-text richiede un input JSON che sia della
forma seguente:

                  Figura 3.9: JSON di input servizio Speech-to-text

    L'elemento "cong" contiene la congurazione necessaria per elaborare correttamen-
te la richiesta. È necessario ad esempio specicare la lingua, la codica audio e la sua
frequenza. Segue un immagine che descrive i parametri richiesti.

                                          23
Figura 3.10: Dettaglio "cong" JSON di congurazione

   L'elemento "audio" invece contiene l'audio vero e proprio. La caratteristica interes-
sante del servizio consiste nel fatto che è possibile usare come valore per questo campo

                                          24
una stringa, che costituisce la rappresentazione del le audio in codica base 64. Il fra-
mework Spring ore un metodo che permette di convertire un oggetto Java di classe
File in un array di byte. Una volta ottenuto l'array, è suciente utilizzare un metodo
statico contenuto nel package java.util.Base64 per ottenere la stringa desiderata. Una
volta eettuate queste operazioni è suciente inserire la stringa come valore del campo
"content" e si ottiene il JSON di input da inviare a Google.

                Figura 3.11: Dettaglio "audio" JSON di congurazione

   Se tutto è andato a buon ne, il servizio risponde con un altro JSON della seguente
forma:

                                           25
Figura 3.12: JSON di risposta

    Il campo "transcript" contiene la stringa di testo che corrisponde a ciò che l'utente
ha detto nel messaggio vocale.
Dopo aver convertito l'audio inviato dall'utente in una stringa testuale, si è reso necessario
utilizzare un servizio che aiutasse a capire la richiesta dell'utente. Google ore delle
API REST che svolgono proprio questa funzione. Come per lo speech-to-text, le API
accettano come input un JSON e ne restituiscono un altro che contiene l'analisi sintattica
della frase inviata.

                                             26
Figura 3.13: JSON di input Natural Language API

     Come si vede in gura, è necessario specicare il tipo di input inviato, che nel caso
di una stringa è PLAIN_TEXT, la lingua e la frase da analizzare. Ho quindi estrapolato
il risultato ottenuto dal servizio di speech-to-text e l'ho inserito come valore del campo
"content". Ciò che si ottiene in risposta è un JSON di questo tipo:

                                           27
Figura 3.14: JSON di risposta Natural Language API

   L'oggetto di interesse è l'array di token restituito. Ciascun token rappresenta un
elemento sintattico della frase e, per ognuno di essi, si ottengono le seguenti informazioni:
   • text: è il token oggetto di analisi

   • partOfSpeech: è la parte del discorso (nome, articolo, pronome...) di cui il token
      fa parte.
   • dependencyEdge: rappresenta la relazione che intercorre tra il token e suo padre,
      un altro token a cui è collegato.
    Nel complesso ciò che si ottiene è l'analisi di ciascun elemento della frase, insieme
al tipo di relazione che intercorre tra elementi diversi. Nella documentazione questo
concetto è chiamato dependency tree ed è rappresentato mediante questo esempio:

                        Figura 3.15: Esempio di dependency tree

                                             28
Questo strumento si è rilevato cruciale per capire la richiesta dell'utente nel caso in
cui un input fosse composto da parole multiple. Nello specico, il modo con cui il bot
interpreta una frase intera è il seguente:
   • Come prima cosa bisogna capire in quale conversazione vuole entrare l'utente,
      quindi si scorrono i token in cerca delle parole chiave "fatturato" o "margine".
   • Una volta entrato in conversazione, l'utente si trova nel suo primo stato, a cui sono
      associati una serie di input che permettono la transizione ad uno stato successivo.
      Solitamente gli input sono composti da una parola, quindi si scorre la lista di token
      in cerca di un match con uno degli input accettati dallo stato corrente. Se il match
      ha successo, si passa ad un altro stato e si ripete il processo no ad arrivare ad uno
      stato nale. Può capitare però che l'input accettato sia composto da più parole.
      In questo caso si rivela fondamentale sfruttare l'albero di dipendenza fornito dalle
      API. Per ogni token è possibile infatti risalire l'albero, componendo un passo alla
      volta il token glio con il padre, tentando il match con uno degli input, no ad
      arrivare alla radice.
    In questo modo si evita di comporre token che non hanno relazione logica tra loro
per tentare il match con input formati da più parole.
Usando questo approccio vengono soddisfatte entrambe le condizioni descritte al capitolo
3.3.2.

Google BigQuery
Una volta arrivati a uno stato nale di una conversazione, è necessario reperire i dati.
Ciò signica eseguire una query a un database. Si è reso necessario quindi, discriminare il
caso in cui la query andasse eseguita su un database locale dall'interrogazione al database
in cloud mediante BigQuery. Per separare i due casi ho inserito in ciascuno stato nale,
un campo booleano che specicasse dove la query andasse eseguita. I risultati della query
vengono restituiti da Google in formato JSON, ho quindi implementato un servizio che
convertisse il JSON nello stesso oggetto Java usato per rappresentare i dati restituiti
dall'esecuzione della query in locale. In questo modo l'esperienza utente è stata resa
uniforme in entrambi i casi.

Struttura del bot
Ho strutturato il bot in due livelli distinti:
   • Repository

   • Service
    Il livello Repository è il layer di persistenza dei dati, dove sono denite le entità
Java che corrispondono alle tabelle del database e le relative operazioni CRUD. Il pattern
usato per strutturare questo livello è il Data Access Object. Ciò consente di separare
la logica di business da quella di accesso ai dati.

                                                 29
Figura 3.16: Database Access Object Pattern

    Il funzionamento del pattern è descritto attraverso il seguente esempio.
Supponiamo che nel database sia presente la tabella conversations, che contiene tutte
le possibili conversazioni. Sarebbe comodo avere un modo semplice per operare sulla
tabella lato Java. La soluzione si compone di tre passi:
   • Si implementa una classe Java che corrisponde alla tabella nel database. Questo
     signica che gli attributi della classe devono corrispondere ai campi della tabella.
   • Si implementa l'interfacciaRowMapper, che contiene la logica per convertire i tipi
     di dato dei campi della tabella, negli attributi della classe Java.
   • Si implementa una classe che incapsula le operazioni da eettuare sulla tabella, che
     fa uso della rispettiva classe Java.
   Poniamo di aver bisogno di reperire tutte le conversazioni dal database. Seguen-
do il primo passo del ragionamento, serve una classe Java corrispondente alla tabella
contenente le conversazioni, denita in questo modo:

                   Figura 3.17: Tabella contenente le conversazioni

                                            30
Scriviamo quindi la seguente classe Java, i cui attributi corrispondono a quelli della
tabella. Ciò signica tradurre il tipo di dato SQL in un tipo di dato Java compatibile.
Nel nostro esempio:

    • bigserial e bigint diventano long.

    • string (varchar) diventa String

    • int rimane int.

     Alla ne otteniamo la seguente classe:
public class Conversation {
   private long conversationId;
   private String name;
   private long customerId;
   private int menuIndex;

    // costruttori
    // getter e setter
}

                                    Listing 3.3: Conversation
    Il secondo passo prevede di implementare RowMapper, un'interfaccia fornita da Spring,
che si occupa di reperire i valori dei campi della tabella conversations ed inizializzare
un oggetto Java Conversation, matchando campi con attributi. Più precisamente, i
valori saranno ottenuti dall'esecuzione di una query, e di norma sono incapsulati in un
oggetto di classe ResultSet. Ciò che bisogna fare è estrapolare i valori da questo oggetto
e usarli per inizializzare gli attributi di Conversation, mediante l'uso dei metodi setter.
public class ConversationRowMapper implements RowMapper {

    @Override
    public Conversation mapRow(ResultSet resultSet, int i) throws SQLException {
    Conversation conversation = new Conversation();

    conversation.setConversationId(resultSet .getLong("conversation_id"));
    conversation.setName(resultSet.getString("name"));
    conversation.setCustomerId((resultSet.getLong("customer_id")));
    conversation.setMenuIndex((resultSet.getInt("menu_index")));
    return conversation;
    }
}

                         Listing 3.4: RowMapper per l'entità Conversation
    Avendo a disposizione un modo per convertire i record di una tabella in oggetti Java,
ciò che ci si era pressato di ottenere all'inizio (la lista delle possibili conversazioni)
si traduce di fatto nel reperire una List. Si implementa quindi una

                                                  31
classe che, tra le altre operazioni, permette di assolvere a questo compito mediante il
metodo getConversations().
@Repository
public class ConversationDaoImpl implements ConversationDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List getConversations() {
      return jdbcTemplate.query("SELECT ∗ FROM conversations", new
           ConversationRowMapper());
    }
}

                       Listing 3.5: Reperimento delle entità da query
    Questo metodo fa uso di query(String sql, RowMapper rowMapper). Esso si oc-
cupa di eseguire la query e matchare i valori restituiti, contenuti nell'oggetto di classe
ResultSet, con gli attributi della classe Java Conversation, sfruttando le regole de-
nite in precedenza da ConversationRowMapper.

   Seguendo questa logica ho denito le seguenti classi Java che matchano la rispettiva
tabella presente nel database:
    • Conversation: Modella una conversazione.
    • State: Modella lo stato di una conversazione.
    • User: Modella un utente.
    • Role: Modella un permesso.
    Inoltre ho progettato e implementato le seguenti interfacce, che contengono le opera-
zioni necessarie da eseguire sulle tabelle:
    • ConversationDao: Incapsula le operazioni che si possono eettuare sull'entità
       Conversation.
    • ConversationRolesDao: Incapsula le operazioni che si possono eettuare sulla
       tabella che mette in relazione le conversazioni con i permessi.
    • RoleDao: Incapsula le operazioni che si possono eettuare sull'entità Role.
    • StateDao: Incapsula le operazioni che si possono eettuare sull'entità State.
    • UserDao: Incapsula le operazioni che si possono eettuare sull'entità User.
    • UserRoles: Incapsula le operazioni che si possono eettuare sulla tabella che
       mette in relazione gli utenti e i permessi.

                                             32
Il livello Service contiene la logica del bot e fa uso del livello Repository. I servizi
implementati sono i seguenti:
   • ConversationService: Incapsula la logica delle conversazioni. In particolare:

         Permette di ottenere la lista delle coversazioni presenti nel database.
         Permette di ottenere la lista delle conversazioni a cui un determinato utente
          è abilitato ad accedere.
   • GoogleCloudService: Incapsula le chiamate REST alle API di Google usate per
     lo speech-to-text e per l'analisi sintattica. In particolare:
         Dato un input accettato per lo speech-to-text, permette di ottenere il JSON
          contenente il risultato della conversione audio/testo.
         Dato un input accettato dal servizio di analisi sintattica, permette di ottenere
          il JSON contenente l'analisi dell'input.
   • HighchartsService: Incapsula il servizio Highcharts per la generazione dei graci.
     In particolare:
         Dato un JSON contenente i parametri del graco che deve essere generato,
          permette di ottenere un oggetto di classe File che contiene il graco richiesto.
   • HTTPService: Permette di eettuare una chiamata HTTP di tipo POST ad un
     certo url, inviando un JSON come parametro di input.
         Dato un le JSON di input e un oggetto di classe URL, contenente l'indirizzo
          a cui eettuare la richiesta, permette di ottenere una stringa contenente il
          risultato della chiamata HTTP.
   • JsonService: Permette la creazione e manipolazione di oggetti JSON. In partico-
     lare:
         Dato un oggetto di classe File, contenente un audio, restituisce un JSON
          che rappresenta l'audio in formato base64, nella forma accettata dal servizio
          Google per lo speech-to-text.
         Data una stringa di testo contenente il risultato del servizio di speech-to-text,
          permette di ottenere un JSON nella forma accettata dal servizio di analisi
          sintattica.
         Data una stringa di testo contenente una query da eseguire tramite il servizio
          BigQuery, permette di ottenere un JSON accettato dal servizio, che incapsula
          la query.
   • LevenshteinService: Permette di confrontare stringhe di testo tra loro per veri-
     carne l'uguaglianza considerando un certo margine di errore. In particolare:

                                            33
 Data una stringa da matchare, un array di stringhe, e una soglia di errore,
       permette di ottenere l'indice dell'elemento nell'array che costituisce il miglior
       match, ammettendo una certa soglia di errore. Ad esempio, la stringa "fattu-
       rat" e l'elemento dell'array "fatturato", costituiscono un match con soglia di
       errore 1.
• MessageService: È il servizio che si occupa di comporre i messaggi da inviare
  all'utente. In particolare:
      Permette di comporre un messaggio con una inline keyboard associata.
      Permette di comporre il messaggio testuale da restituire all'utente contenente
       i dati estratti dal database.
• NavigationButtonService: È il servizio che permette di comporre la tastiera
  generale mostrata all'utente. In particolare:
      Dato un utente, restituisce la tastiera generale contenente solamente le con-
       versazioni a cui l'utente è abilitato ad accedere (ha i permessi sucienti).
• PicService: È il servizio che si occupa di comporre la foto di un graco generato
  mediante Highcharts.
• SpeechConversationService: È il servizio che permette di interpretare la stringa
  ottenuta dal servizio di speech-to-text. Ovvero cerca di matchare l'input di un certo
  stato con un insieme di parole, relazionate tra loro dalle API Natural Language.
• StateService: È il servizio che implementa la logica di movimento tra gli stati
  della conversazione.
• UpdateService: È il servizio di alto livello che si occupa di gestire la ricezione di
  un messaggio vocale o testuale.
• UserService: È il servizio che si occupa di gestire l'utente, in particolare gestisce
  il suo stato di conversazione.
• BigQueryService: È il servizio che incapsula le chiamate REST alle API Big-
  Query di Google. In particolare:
      Dato un input accettato dal servizio BigQuery, permette di ottenere un JSON
       contenente il risultato della query.
• DriveSpreadsheetService: È il servizio che permette di leggere i dati di congu-
  razione (utenti, permessi, conversazioni e stati) del bot da fogli Drive e li importa
  nel database locale.
• GCredentialService: È il servizio che incapsula il meccanismo di autenticazione
  OAUTH2 di Google.

                                        34
• ScheduledJobService: È il servizio che si occupa periodicamente di vericare
      se i permessi di un utente sono stati modicati, inviando la tastiera aggiornata di
      conseguenza.

Funzionamento del bot
Per poter ricevere i messaggi mandati dagli utenti, è necessario creare una classe che
estenda TelegramLongPollingBot, denita nelle API, ed eettuare l'override del metodo
onUpdateReceived(Update). Un oggetto Update rappresenta un messaggio mandato al
bot, può essere di tipo testuale, un audio, un'immagine, una posizione ottenuta dal GPS o
un generico le inviato in allegato. La prima cosa da controllare è che l'update sia di tipo
testuale o audio, poiché questi sono gli unici input accettati dal bot. Subito dopo bisogna
assicurarsi che l'utente sia abilitato ad accedere al bot, ciò è prerogativa del servizio
UserService, che accede al database delegando la richiesta al livello Repository. Una volta
autenticato l'utente, si procede ad inviare la tastiera attraverso cui può inviare comandi al
bot. Questo compito è svolto da NavigationButtonService che compone in modo dinamico
la tastiera a seconda dei permessi specici dell'utente per ogni conversazione.

                                             35
Figura 3.18: Schermata iniziale con generazione dinamica tastiera

    Successivamente viene delegata la gestione di un messaggio testuale o vocale a due
metodi diversi del servizio UpdateService, che si occupano di elaborare la richiesta a
seconda del caso specico.
   • Messaggio testuale: Quando viene ricevuto un messaggio, l'utente può trovarsi
     già all'interno di una conversazione (quindi è in uno stato), oppure no. Nel caso
     in cui non si trovi in una conversazione viene controllato se l'utente ha i permessi
     per accedere alla conversazione selezionata, e in caso positivo, viene registrato nel
     database che l'utente è nel primo stato di una certa conversazione, dopodiché si
     esegue l'output dello stato iniziale. Questo signica che il bot invia un messaggio
     per capire cosa l'utente desideri sapere, insieme a dei bottoni che corrispondono
     agli input accettati per lo stato.

                                           36
Figura 3.19: Output stato iniziale Fatturato

Può succedere anche che l'utente non si trovi in nessuna conversazione, ma nella
cronologia dei messaggi sia presente un messaggio con dei bottoni associati, che
puntano ad un certo stato di una conversazione passata. Se l'utente preme su uno
di questi bottoni il bot è in grado di capire lo stato e la conversazione associati al
bottone, quindi, dopo aver controllato i permessi, inserisce l'utente direttamente
nello stato e nella conversazione desiderata.
Se l'utente si trova già all'interno di una conversazione, il bot è in attesa che l'utente
prema su uno dei bottoni associati al messaggio, che costituiscono una transizione
verso un altro stato. Quando questo si verica, lo stato corrente dell'utente viene
aggiornato e si esegue l'output del prossimo stato. Si prosegue in questo modo no
al raggiungimento di uno stato nale, dove si possono vericare due scenari:
   I dati da restituire all'utente devono essere in formato testuale.
   I dati da restituire all'utente devono essere sotto forma di graco generato da
    Highcharts.

                                        37
Se il formato in cui restituire i dati è testuale, nel database è presente una stringa
di testo che costituisce il template di risposta in cui vengono inseriti i dati ottenuti
mediante l'esecuzione della query associata allo stato. I dati vengono iniettati in
questo template mediante la sostituzione di un carattere speciale inserito a questo
scopo.

                         Figura 3.20: Output testuale

Ad esempio, in riferimento alla gura precedente, sono stati iniettati i dati corri-
spondenti alla data corrente e il valore del fatturato nella stringa "Il fatturato YTD
al # è di # euro".
Se bisogna restituire un immagine, il principio di funzionamento è lo stesso, ma i
dati vengono iniettati in un JSON di template dal servizio PicService.

                                       38
Figura 3.21: Output graco

  Una volta restituiti i dati nella forma richiesta, l'utente viene fatto uscire dalla
  conversazione corrente poiché è stato raggiunto uno stato nale.
• Messaggio vocale: Anche nel caso in cui il bot riceva un messaggio vocale lo sce-
  nario di partenza non cambia, l'utente può trovarsi già all'interno di una conversa-
  zione oppure no. Se l'utente non si trova all'interno di una conversazione, bisogna
  cercare all'interno dei token restituiti dal servizio di analisi sintattica, quello che
  corrisponde al nome di una delle conversazioni a cui l'utente è abilitato ad accedere.
  Una volta trovato, si inserisce l'utente all'interno della conversazione giusta, e ci
  si riconduce al caso in cui l'utente si trovi già all'interno di uno stato. Si procede
  quindi ad elaborare il messaggio cercando un input accettato per lo stato corrente,
  e in seguito per gli stati successivi attraverso il metodo descritto al capitolo 3.3.3.
  Nella gura che segue, è rappresentato l'invio del messaggio vocale: "Qual è il
  fatturato per mese con graco?".

                                         39
Figura 3.22: Elaborazione messaggio vocale

    Il bot consente inoltre di reperire informazioni su parametri critici con un solo click.
L'azienda mi ha infatti chiesto di aggiungere alla tastiera di navigazione il pulsante "Come
va oggi?", che indica all'utilizzatore del bot se ci sono dei valori fuori soglia, in modo da
poter intervenire tempestivamente. Per implementare questa funzionalità, ho aggiunto
una tabella nel database dove tengo traccia delle soglie di tolleranza accettate per ciascun
indicatore.
Alla pressione del pulsante, vengono reperiti i valori correnti di tutti gli indicatori e, per
ciascuno di essi, viene controllato se rientrano nelle soglie specicate. Tutti i valori fuori
soglia vengono noticati all'utente.

                                             40
Puoi anche leggere