RUTE Posted April 6, 2013 Report Posted April 6, 2013 Ganditi-va cat de usor ar fi daca am avea cativa "servitori" care sa faca totul in locul nostru: sa aduca posta, sa curete cusca papagalului - chestii de genul asta. Din pacate, suntem putin cam devreme in timp pentru astfel de roboti ieftini si eficienti in acelasi timp, deci trebuie sa trecem peste asta. In schimb, in lumea virtuala, asta este deja posibil, sa avem acest robot care care face lucrurile in locul nostru. Da, asta e o descriere a oricarui software, dar la ce ma gandesc mai exact este ceva cu o interfata 'easy-to-use' care sa poata face un task folositor si sa iti spuna lucrurile de care ai nevoie.Un mod neconventional dar convenient pentru comunicarea cu astfel de roboti este prin chat. Pana la urma, de ce sa ne complicam folosind tunnele SSH sau alte aplicatii plictisitoare de tip 'bidding-do', cand putem comunica printr-un mediue pe care oricum il folosim foarte des. Intr-o scurta prezentare, robotelul nostru va fi un chatbot care va astepta sa auda vocea stapanului sau printr-un canal de chat, sau chiar sa iti trimita anumite informatii, cand e nevoie.Eu sunt XmpppyProtocolul Jabber/XMPP este bine acoperit de Python. Exista ca si o parte a bine-cunoscutului modul de retea, Twisted, dar exista si o implementare a lui mai 'lightweight' care e suitabila pentru ceea ce avem noi nevoie, cunoscuta sub numele de Xmpppy. E posibil sa gasiti un pachet de date pentru distributia care o folositi, dar mai simplu este sa descarcati direct codul Python de la xmpppy: the jabber python project .Ca sa intelegeti cum sa folositi Xmpppy, o sa incepem prin cateva exemple din linia de comanda, dar inainte de asta aveti nevoie de un cont pe care sa il incercati. Puteti crea un nou cont Google pentru acest bot, de exemplu. De asemenea, o a aveti nevoie de doua conturi de Jabber pentru aceste teste. In acest tutorial, voi folosi propriul cont de Google, logat printr-un web browser, de pe care voi invita un alt cont Google la chat. Puteti face asta prin Xmpppy direct, dar devine mai complicat - pentru inceput, e mai bine sa avem doua conturi care pot deja comunica intre ele. Cand sunteti gata, scrieti python in shell pentru a avea acces la linia de comanda interactva Python:>>> import xmpp>>> jid=xmpp.protocol.JID("adresa.bot@gmail.com")Ok, primul lucru care l-am facut a fost sa setez un ID de Jabber. In cazul nostru, arata ca si o adresa de email, deoarece folosim un cont Google pentru acest tutorial, dar de fapt, orice ID Jabber functioneaza. Efectiv, sunt doua parti, anume username-ul si domain-ul. Domeniul este acolo unde Xmpppy se asteapta sa gaseasca serverul. Acum ca am stabilit userul, ar trebui sa pornim o sesiune a obiectului client. In Xmpppy, clientul este obiectul care controleaza conexiunea, transmite mesajele si interactioneaza cu serverul. Exista cativa pasi pentru a crea acest client si a ne conecta la el. In primul rand, trebuie sa cream o sesiune a clientului (care va avea ca argument un Jabber ID) si apoi vom incerca sa stabilim o conexiune cu serverul. Odata ce conexiunea a fost facuta, trebuie sa ne autentificam inainte sa putem face altceva.>>> myclient=xmpp.Client(jid.getDomain(),debug=[])>>> myclient.connect()'tls'>>> myclient.auth(jid.getNode(),'parolabot')'sasl'Aici voi explica procesul. In primul rand, am creat o sesiune a clientului, si am folosit functia jid.getDomain pentru a obtine numele serverului de la obiectul jid pe care deja l-am creat. De asemenea e nevoie sa facem un debug level, care va controla feedbackul primit. Al nostru a fost setat la o lista goala, dar daca intradevar va doriti sa aveti ecranul plin cu mesaje, puteti sa introduceti stringul always in lista, desi ar putea cauza probleme.Sa ne conectamDupa ce am setat debug levelul, am creat o conexiune si am primit inapoi raspunsul tls, care ne arata ca o conexiune securizata a fost stabilita cu serverul - s-ar putea sa primit ca raspuns tcp, care reprezinta o conexiune standard, sau un string empty daca nu s-a facut conexiunea.Acum, depinzand de viteza cu care scrieti si de server, urmatorul pas s-ar putea sa nu functioneaza. Asta e din cauza faptului ca serverele Google se asteapta sa va autentificati foarte repede, in caz ca nu o faceti conexiunea se va inchide si veti avea batai de cap, gandindu-va de ce nu functioneaza. Aveti doar cateva secunde la dispozitie, deci ar fi mai bine sa va puneti urmatoarele linii de cod intr-una singur din linia de comanda:>>> myclient.connect() ; myclient.auth(jid.getNode().'parolabot')'tls''sasl'Rezultatul sasl va arata ca ati fost conectati folosind SASL (Simple Autenthiation and Security Layer) conform parolei dumneavoastra. Exista un ultim pas pentru a initializa conexiunea, el fiind reprezentat de a ii "spune" serverului ca sunteti prezenti. Dupa cum stiti, pe Google Chat si alte servicii Jabber, exista mai multe tipuri de prezente (Available sau Busy, de exemplu). Aparte de altele, acestea sunt folosite de server pentru a crea liste de contacte, si in Xmpppy avem o solutie simpla pentru a face asta:myclient.sendInitPresence()Tineti minte ca unele servere ar putea sa nu va lase sa faceti o conexiune daca gresiti acest pas.Mesajele trimiseOkay, ne-am conectat! Acum, inainte sa devina prea plictisitor, haideti sa construim si sa trimitem un mesaj chat catre tinta noastra (de exemplu, propria adresa Google). Trebuie sa stim cateva lucruri inainte, totusi - adresa la care trimitem, si mesajul in sine. Dupa ce am stabilit acestea doua, vom crea o sesiune de mesaje si trimite:mymsg=xmpp.protocol.Message("adresabot.1@gmail.com","salut","chat")myclient.send(mymsg)Asumandu-mi ca deja ati fost invitat la chat de catre bot si ati acceptat, ar trebui sa aveti o surpriza placuta.DOCUMENTATIE API: API DocumentationCa o mica paranteza, protocolul XMPP va lasa sa trimiteti mesaje catre tinte individuale, si exista cateva metode primite pentru asta, dar de ce sa nu lasam serverul sa aiba grija de asta:>>> presence = xmpp.Presence(status="Ready!",show = "chat", priority = '1')>>> myclient.send(presence)Modulul Xmpppy obisnuieste sa trimita intr-un alt mod aceste mesaje, din cauza argumentelor diferite, dar mecanismul de trimitere este acelasi.Mesajele primiteDe asemenea, pentru un bot complet functional, o sa avem nevoie si sa primit mesajele, un lucru putin "tricky", trebuie sa recunosc. Frameworkul Xmpppy va primi mesajele trimise catre sesiunea client objectului pe care l-ati creat si le va pune intr-un "stack" pentru a fi procesate. Dar cum vor fi procesate? Ei bine, Xmpppy foloseste un concept numit "handlers". Inainte sa putem procesa un mesaj, o variabila (ca sa putem raspunde), poate ar trebuie sa alegem o tinta care sa trimita mai departe mesajul.Pentru acest bot simplu, vom adopta o sintaxa care reprezinta mai multe comenzi speciale care pot fi trimise catre bot prin adaugarea in fata lor a unui '#'. Asadar, daca un mesaj apare cu acest caracter in fata, vom putea sa dam o comanda pentru a face ceva cu el. In caz contrar, va fi returnat un mesaj la intamplare din lista.Folosirea unui shortcutAdaugarea unui handler pentru aceste comenzi poate ocupa o multime de timp si spatiu. Pentru a salva acestea doua, clasa de care ne vom folosi va defini intr-un fel un shortcut. Folosindu-ne de functia eval din Python, vom construi o functie care sa cheme o metoda in aceasta clasa cu acelasi nume prin care comanda este trimisa. Da, v-ar putea baga putin in ceata aceasta metoda, dar cu siguranta va salva timp si efort - trebuie doar sa definiti o noua metoda si voila! Ati putea, pentru un chatbot mai performanta, sa adaugati comenzi extra, dar eu va voi arata metoda mai simpla:def messageparse(self, instance, message): m = message.getBody() sender=message.getFrom() if (m[0]=='#'): self.log('command received') #cazurile speciale vor fi scrise aici #comenzile generale - au nevoie de o metoda deja existenta, si de id-ul expeditorului try: eval('self.'+m[1:]+(sender)') except: self.client.send((xmpp.protocol.Message(sender, 'Imi cer scuze, dar nu pot face asta...'))) else: #o sa spunem ceva incercand sa fim politicosi self.client.send((xmpp.protocol.Message(sender, random.choice(self.responses))))Dupa cum putem vedea aici, mesajul este verificat daca , contine #, si in caz ca el exista, este contruita o metoda care diferentiaza de restul stringului, incluzand ID-ul expeditorului si incercand sa execute comanda. Constructiile try si execute sunt pentru exceptii, ca de exemplu atunci cand metoda nu exista. Daca nu este trimisa nicio comanda, trimitem un mesaj inapoi, ales la intamplare dintr-o lista numita responses. In lumea reala, ar trebuie sa importati un modul random pentru asta; random.choice pur si simplu alege un item la intamplare din ceea ce ii oferiti.Prin urmare, un exemplu de handler ar fi:def uptime(self,sender):import subprocessp=subprocess.Popen(["uptime"], stdout=subprocess.PIPE)r=p.communicate()[0]self.client.send((xmpp.protocol.Message(sender,r)))Aici voi incerca sa detaliez cat de bine pot, pentru ca tine de executarea comenzilor local pe masina pe care botul ruleaza. In primul rand, avem definitia, care accepta propria sesiune (lucru necesar in Python). De asemenea am importat din librariile standard ale Python subprocess pentru a putea executa comenzile local.De asemenea am folosit metoda numita Popen (vedeti linia care incepe cu p=subprocess.Popen), a carei documentatii o puteti gasi explicata in detaliu la: 17.1. subprocess — Subprocess management — Python v2.7.3 documentation.Cam asta a fost tot pentru tutorialul de astazi, sper ca am explicat bine incat toata lumea sa intelegea.TIPS&TRICKS:1. Pentru cei care doresc sa continue acest proiect, puteti gasi documentatia XMPP de la Google la adresa: http://code.google.com/apis/talk/jep_extensions/extensions.html .2. Python a scos destul de recent versiunea 3.x, insa codul nostru nu este compatibil cu acesta. Eu am folosit pentru acest tutorial versiunea de Python 2.x , versiune inca folosita de majoritatea userilor.3. Va recomand sa folositi un editor de Python cu syntax highlighting. Recomand Vim sau Kate. Sau puteti lua ceva care este folosit DOAR pentru Python, si specializat in asta, Eric.Succes! Quote