.. _services/creare_service: 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 :ref:`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. .. hint:: 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 :ref:`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``):: In questo secondo caso le *api_keys* così definite saranno sempre reperibili in ``self.site.getApiKeys('telegram')`` .. A volte viene fatto questo, potrebbe servire per "svincolarsi" dal service_name??? ??? 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 :ref:`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. .. sectionauthor:: Davide Paci