Come creare un service

È possibile creare un service personalizzato all’interno di un qualsiasi package creando un file nomedelservice.py all’interno della cartella resources > services > service_type. Ad esempio:

packages > genrobot > resources > services > telegram > telegram.py

Il file del service deve necessariamente contenere una classe Main, che eredita da GnrBaseService, e una classe ServiceParameters, che servirà a raccogliere eventuali parametri per il funzionamento del service. Vediamo innanzitutto come specificare i parametri del service.

I parametri del Service

Esistono due modalità di definizione dei parametri del service, strettamente legata alla modalità di funzionamento del service :

  • all’interno dell’applicativo Genropy, per service funzionanti in modo «attivo», tramite la definizione della classe ServiceParameters

  • nel file instanceconfig.xml, per service funzionanti in modo «passivo»

Nel primo caso è possibile ridefinire nel file del service la classe ServiceParameters e il metodo service_parameters al suo interno:

class ServiceParameters(BaseComponent):
  def service_parameters(self, pane, datapath=None, **kwargs):
      cp = pane.borderContainer(region='center').contentPane(region='top')
      fb = cp.formbuilder(datapath=datapath)
      fb.textbox(value='^.access_token', lbl='Access Token')
      fb.textbox(value='^.verify_token', lbl='Verify Token')

In questo caso inseriamo un normale Formbuilder che ha lo scopo di permettere all’utente di inserire le sue credenziali (un access_token e un verify_token). Questo metodo fornirà al Main questi parametri per l’utilizzo nei metodi successivi.

Suggerimento

Questo modo di identificare i parametri è strettamente legato al fatto che l’istanza sia attiva e il service venga «invocato» manualmente. Diverso è il caso seguente, in cui invece il service è sempre attivo e in ascolto a prescindere dalla presenza o meno di un’istanza attiva, grazie al processo gnrserviceworker

Nel secondo caso, invece, in caso di service che operano anche a istanza inattiva e sono sempre in ascolto, gli eventuali parametri devono essere inseriti nel file instanceconfig.xml dell’istanza o alternativamente nell’instanceconfig di default di Genropy (.gnr/instance/default.xml):

<api_keys>
              <telegram api_id="XXXXXXX" api_hash="8b1cfd24...........15f4c" />
</api_keys>

In questo secondo caso le api_keys così definite saranno sempre reperibili in self.site.getApiKeys('telegram')

La classe Main del Service

La classe Main deve definire le azioni che eseguirà il service (es: istanziamento client, azioni get/post, ecc). Ad esempio:

class Main(GnrBaseService):
    def __init__(self, site, access_token=None, verify_token=None, **kwargs):
        self.site = site
        self.api_keys = self.site.getApiKeys('telegram')
        self.access_token = access_token
        self.verify_token = verify_token

Nell’esempio, all’interno del metodo __init__, metodo obbligatorio eseguito automaticamente dal Main, stiamo istanziando il service con le credenziali necessarie al suo funzionamento, in particolare:

  • recuperiamo le ApiKeys dall’istanza, specificate nel file instanceconfig.xml

  • rendiamo disponibili ApiKeys e i parametri access_token e verify_token (specificati nei parameters) per gli altri metodi che eseguiranno le varie azioni del service.

A questo punto sarà possibile definire altri metodi a piacere nel Main per specificare le azioni da eseguire. Ad esempio:

@public_method
  def publishPost(self, access_token=None, page_id_code=None, message=None, **kwargs):
      with self.client(bot_token=access_token) as c:
           text = message
           c.send_message(page_id_code, text)
      return message

Il service sarà già attivo e funzionante in modalità «attiva». Per il funzionamento in modalità passiva, sarà invece necessario creare un altro file service.py nella lib.

Service passivi: file nella lib

Per i soli service passivi è necessario creare anche un file dal generico nome service.py all’interno della lib di Genropy, in una cartella che chiameremo con il service_type, ad esempio:

packages > genrobot > lib > services > telegram > service.py

Questo file è quello che verrà contattato dal processo gnrserviceworker per l’avvio del service. Conterrà quindi necessariamente una classe Service e un metodo __init__:

from gnr.web.gnrwsgisite import GnrWsgiSite

class Service(object):
  def __init__(self, instance_name=None, service_name=None, **kwargs):
      self.site = GnrWsgiSite(instance_name)
      self.service = self.site.getService('telegram', service_name)

All’interno di questo metodo __init__, utilizzando la getService, esattamente come nel caso di funzionamento attivo del service, individuiamo il service e lo istanziamo. È possibile poi anche in questo caso aggiungere altri metodi a piacere per il compimento delle diverse azioni di interesse.

Autore della sezione: Davide Paci