Pesquisa personalizada

2008/11/19

E-mails com Pedidos do Mercado Livre + GMail * Greasemonkey = Produtividade

Já faz algum tempinho que acumulei centenas de vendas no Mercado Livre. Em tempos de gloria, chegava a fazer mais de uma dezena de vendas ao dia e isso trouxe a problemática de atender aos clientes de forma ágil e adequada. E a verdade, é que o simples processo (sem falar nos outros) de enviar o e-mail com os dados do pedido ao cliente, me aborrecia pelo tempo perdido.

O Paulinho, um amigo, me disse que o bom programador, era antes de tudo, um grande preguiçoso. Eis-me: A preguiça personificada! Raramente repito duas tarefas da mesma forma, sempre dou um jeitinho de melhorar (nos meus critérios) o processo, seja o que for... Obviamente, as vezes, decaio na inprodutividade, no perfeccionismo imperfeito e na tolice aguda! Mas mesmo assim, invento e reinvento! Até, no ápice do sucesso, faço funcionar!

A questão é que, contrariando qualquer instinto (por mais forte que fosse), resisti a tentação de fazer um script, ou até mesmo, simplesmente criar uma regra/filtro que me ajudasse na simples tarefa de responder com os dados da compra de meus clientes. Visto que me despersuadia:
- "Não seja tolo, Marcio. Vai perder ainda mais tempo com isso."
Sinceramente, nem me reconheço com essa atitude, mas é verdade: resisti!

A questão, é que depois de fazer a mesma coisa por mais de 800 vezes (real!! foi mais que isso mesmo!), você pára (logo agora que tentava escrever direito, me tiram o tal do acento... <0) e, após xingar toda seus antepassados - se excomungar -, diz:
Devia ter automatizado isso antes...

EMail com Pedido do Mercado Livre

Eis, logo eu que atualmente me vejo trabalhando nuns trocentos projetos ao mesmo tempo e tentando ser dono de meu próprio narzi, mas ao contrário, cada vez mais preso... me vejo tomado por uma completa indignação por fazer a mesma tarefa por quase 1000 vezes e digo a mim mesmo:
- basta! Vou automatizar isto!

Chega o momento de ver o que seria melhor. Com certeza o melhor é criar um sistema, baseado em uma base de dados, que concentre todas as informações de compra, inclusive passadas e que fosse integrada com a "maravilha" do ML... até fiz vários progressos nesse sentido, mas parei no ponto onde precisava alimentar a base com os dados que retirava de 5 (sim, cinco!) diferentes páginas do ML e mantê-los de uma forma racional e principalmente utilizável!

Optei, então, por me concentrar somente no simples problema de responder ao cliente com os dados de sua compra, como: onde pagar, o quanto pagar, onde fazer etc. Isso poderia simplesmente ser feito com um filtro no GMail, por exemplo e até soluções mais elaboradas via VBA, por exemplo, com o Outlook. Mas queria uma coisa que NÃO funcionasse totalmente por si só, que ainda precisasse de minha leitura prévia (e rápida). Por isso, já que atualmente ando trabalhando tanto com AJAX e naturalmente Javascript (como se nunca o tivesse feito antes [8 anos atrás já usava DHTML e AJAX, sem nem saber que o nome desse tipo de coisa era isso]) que fosse simples e perfeitamente integrado à minha rotina.

Após estudar as opções, resolvi botar o meu velho entusiamo no Greasemonkey para render algo e fui atrás de alguma alguma API do GMAIL que funcionasse bem com ele. Nessas horas, é ótimo descobrir que você é um tolo nada original, vi que já haviam criado tal API - algo simples, mas que resolve o mínimo. Daí então, foi só botar a mão em XPath, RegEx, DTHML/DOM e, claro, não poderia faltar, o Firebug.

Firebug

E é esse, meu pequeno legado, e sei que não evitará que ainda assim me chamem de pária ou até mesmo lammer, mas eventualmente, inspirará (nem que seja o desprezo) alguém. Não sei quantos programadores vendem no ML, mas deve ter mais alguém; creio.

À Programação

O Greasemonkey tem uma variável com um objeto mágico chamado de nome window que encapsula a window "real". Se quiser acessar o objeto window real, na verdade, terá que usar unsafeWindow. Isso vale para qualquer variável global, pois ela só estará acessível em unsafeWindow. Isso é causa de muita dor de cabeça para os iniciantes no Greasemonkey. Por exemplo, a instância do console do Firebug só existe em unsafeWindow.

EMail já preenchido com os dados do pedido

O GMail te disponibiliza o objeto unsafeWindow.gmonkey e é por meio dele que você interage com o DOM do GMail e particularmente, alguns de seus membros. Antes de avançar no uso de unsafeWindow.gmonkey, você vai precisar informar ao GMail que deseja (sim o suporte ao Greasemonkey, graças a um funcionário da Google, é da própria Google) carregar o módulo do GMonkey. Para mais informações, leia a:
API reference for version 1.0 of the experimental Gmail Greasemonkey API.

Após se obter acesso à DOM (DHTML) do GMail, o resto é trivial e atualmente, totalmente dependente da estrutura atual do GMail, ou seja, em futuras modificações do GMail, corre-se o risco do código que funcionava antes parar de funcionar.

Para flexibilizar e facilitar o acesso à DHTML do GMail, preferi o uso conjunto de XPath e RegEx pelo poder inerente dessas linguagens de consultas.

O funcionamento é basicamente clicar em "Reply" no e-mail que foi recebido do Mercado Livre (com os dados da compra do cliente) e ir até o Greasemonkey e acionar o comando "Preencher Dados de Compra". Com isso, de forma automática e quase mágica, todos os dados, de todos os campos, serão preenchidos, e, inclui, seguintes recursos:

  • Preenchimento do Nome/Email do destinatário (o cliente);
  • Suporte a uma template de resposta HTML onde todos os campos são preenchidos de forma automática. Os dados são obtidos do email original que foi enviado pelo ML;
  • Cálculo automático do total da compra e incluindo o frete (padrão) e quantidade adquirida.
   1:// ==UserScript==
   2:// @name           GMail - Pedidos do ML
   3:// @namespace      net.marciowb.gmail.ml.pedidos
   4:// @description    Me ajuda a preencher os pedidos do ML - by Marcio Wesley Borges<marciowb@gmail.com>
   5:// @include        http://mail.google.com/mail/*
   6:// ==/UserScript==
   7:
   8:const GMONKEYVER = "1.0";
   9:var gmail = null;
  10:var console = null;
  11:
  12:function evaluateXPath(xPath, aNode) {
  13:        if (!aNode) {
  14:                aNode=document;
  15:        }
  16:        var res = aNode.ownerDocument.evaluate(xPath, aNode, null, XPathResult.ANY_TYPE, null);
  17:        switch (res.resultType) {
  18:                case XPathResult.STRING_TYPE:
  19:                        return res.stringValue;
  20:                case XPathResult.NUMBER_TYPE:
  21:                        return res.numberValue;
  22:                case XPathResult.BOOLEAN_TYPE:
  23:                        return res.booleanValue;
  24:                default:;
  25:        }
  26:        var foundNodes = new Array();
  27:        var item = res.iterateNext(); 
  28:        while (item) {
  29:                foundNodes.push(item);
  30:                item = res.iterateNext();
  31:        }
  32:        return foundNodes;
  33:}
  34:
  35:/**
  36:* Obtém o elemento BODY do e-mail que está sendo composto (criado).
  37:*/
  38:function getComposingMailBody() {
  39:        if (!gmail)
  40:                return null;
  41:        var el = gmail.getActiveViewElement();  
  42:        if (!el)
  43:                return null;
  44:        var aa=evaluateXPath("//iframe[@id!='remote_iframe_0']", el);
  45:        if (!aa || aa.length==0)
  46:                return null;
  47:        var doc = aa[0].contentDocument;
  48:        if (!doc)
  49:                return null;
  50:        var body = doc.body;
  51:        return body;
  52:}
  53:
  54:/** 
  55:* Esta função é para ser chamada por dadosCompra().<br>
  56:* @param _gmail É fornecido automaticamente pela função gmonkey.load que chama esta.
  57:*/
  58:function _dadosCompra(_gmail) {
  59:        console = unsafeWindow.console;
  60:        gmail = _gmail;
  61:        
  62:        var bodyElem = getComposingMailBody();
  63:        if (bodyElem==null) {
  64:                window.alert("Antes, é necessário que  um reply no e-mail com os dados da compra do Mercado Livre");
  65:                return;
  66:        }
  67:        
  68:        
  69:        //Tenta obter o "quoted" mail que está sendo respondido
  70:        var aQuoted=evaluateXPath("//div[@class='gmail_quote']", bodyElem);
  71:        if (!aQuoted || aQuoted.length==0) {
  72:                window.alert("Não se deve apagar o quoted mail ainda.");
  73:                return;
  74:        }
  75:        var quotedMailBody = aQuoted[0].innerHTML;
  76:                
  77:        //Obtém o código do anúncio e nome do produto
  78:        var rgx = /;id=(\d*)[^>]*>([^<]*)/
  79:        var m = rgx.exec(quotedMailBody);
  80:        if (!m || m.length<3) {
  81:                window.alert("Isto  funciona para os e-mails de compra do Mercado Livre.");
  82:                return;
  83:        }
  84:        var codAnuncio = m[1];
  85:        var nomeAnuncio = m[2];
  86:        
  87:        //Obtém o nome do comprador
  88:        rgx = /Nome:\s*<b\b[^>]*>(.*)<\/b>/
  89:        m = rgx.exec(quotedMailBody);
  90:        var nomeComprador = m[1];
  91:        
  92:        //Obtém o código, apelido e pontuação do comprador
  93:        rgx = /Apelido:.*id=(\d*)".*[^>]>(.*) \((\d*)\)/
  94:        m = rgx.exec(quotedMailBody);
  95:        var codComprador = m[1];
  96:        var apelidoComprador = m[2];
  97:        var pontuacaoComprador = m[3];
  98:        
  99:        //Obtém a quantidade de produtos comprados
 100:        rgx = /Quantidade:\s*(\d*)/
 101:        m = rgx.exec(quotedMailBody);
 102:        var quantidade = m[1];
 103:        
 104:        //Obtém o preço pelo qual o cliente comprou o produto
 105:        rgx = /Preço:\s*([^<]*)/
 106:        m = rgx.exec(quotedMailBody);
 107:        var descPreco = m[1].replace("R$","").replace("unit.","");
 108:        
 109:        //Obtém o e-mail do comprador
 110:        rgx = /E-mail:[^>]*>([^<]*)/i
 111:        m = rgx.exec(quotedMailBody);
 112:        var emailComprador = m[1];
 113:        
 114:        //Obtém o telefone do comprador
 115:        rgx = /Telefone:\s*([^<]*)/
 116:        m = rgx.exec(quotedMailBody);
 117:        var telefoneComprador = m[1];
 118:        
 119:        //Obtém a cidade do comprador
 120:        rgx = /Cidade:\s*([^<]*)/
 121:        m = rgx.exec(quotedMailBody);
 122:        var cidadeComprador = m[1];
 123:        
 124:        //Obtém o estado do comprador
 125:        rgx = /Estado:\s*([^<]*)/
 126:        m = rgx.exec(quotedMailBody);
 127:        var estadoComprador = m[1];
 128:        
 129:        //Obtém o país do comprador
 130:        rgx = /País:\s*([^<]*)/
 131:        m = rgx.exec(quotedMailBody);
 132:        var paisComprador = m[1];
 133:
 134:        //////////////////////////////////////  
 135:        var VLR_MIN = 4; //Valor mínimo da compra. Isto é realizado por segurança nossa e o objetivo é evitar que um erro qualquer nos cause prejuízo.
 136:        var TIP_FRETE = "Frete por SEDEX";
 137:        var VLR_FRETE = "23.00";
 138:        
 139:        var vlrTotal = (Number(descPreco) * Number(quantidade)) + Number(VLR_FRETE);
 140:        if (vlrTotal<VLR_MIN) {
 141:                window.alert("Erro: o valor total da compra está sendo computado como: " + vlrTotal);
 142:                return;
 143:        }
 144:        
 145:        var TEMPLATE = '<div>Oi,<br> <br> &nbsp;&nbsp; Td blz?<br><br></div><span style="color: rgb(0, 102, 0);">&nbsp;&nbsp; É o seguinte, informa aí:<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Nome: @NOME_COMPRADOR</span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">Endereço:</span></span><br style="font-family: courier new,monospace;"><span style="color: rgb(0, 102, 0);"><span style="font-family: courier new,monospace;">Bairro: </span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">Cidade/Estado: @CIDADE_COMPRADOR-@ESTADO_COMPRADOR </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">CEP: </span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">APELIDO: @APELIDO_COMPRADOR </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">CPF: </span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">TEL: @TELEFONE_COMPRADOR </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">E-MAIL: @EMAIL_COMPRADOR </span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">FORMA DE PAGAMENTO: </span><br><br>E se tu tivé uma companhia, diz, também:<br><span style="font-family: courier new,monospace;">Nome da Empresa: </span><br style="font-family: courier new,monospace;"> <span style="font-family: courier new,monospace;">CNPJ: </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Inscrição Estadual: </span><br></span><br><b style="color: rgb(0, 102, 0);">Importante: </b><span style="color: rgb(0, 102, 0);"><br> Nessa, você  levando:<pre> <br><table border="1" cellspacing="0" cols="3" style="font-family: courier new,monospace;font-size:9pt" rules="groups" width="100%" frame="void"><tbody> <tr> <td width="35" align="right"><b>Qnt.</b></td> <td  align="right" width="94"><b>Valor</b></td> <td align="left"><b>Descrição</b></td> </tr> <tr> <td width="35" align="right">@QNT_PRODUTO</td> <td align="right" >@VALOR_PRODUTO</td> <td>@NOME_PRODUTO</td> </tr> <tr> <td width="35" align="right">@QNT_FRETE</td> <td align="right" >@VALOR_FRETE</td> <td>@TIPO_FRETE</td> </tr> <tr> <td bgcolor="#e6e6e6" align="right" height="16"><b>@QNT_TOTAL</b></td> <td bgcolor="#e6e6e6" align="right" ><b>@VALOR_TOTAL</b></td> <td bgcolor="#e6e6e6"><font size="2"><b>Total</b></font></td> </tr> </tbody> </table><font face="monospace"><br></font></pre> &nbsp;&nbsp; É isso, aí.<br>Valeu brother,<br> Ful. de Talz';
 146:        var emailBody = TEMPLATE
 147:                .replace("@NOME_PRODUTO", (nomeAnuncio+" #"+codAnuncio))
 148:                .replace("@VALOR_PRODUTO", descPreco)
 149:                .replace("@QNT_PRODUTO", quantidade)
 150:                .replace("@QNT_FRETE", "1")
 151:                .replace("@VALOR_FRETE", VLR_FRETE)
 152:                .replace("@TIPO_FRETE", TIP_FRETE)
 153:                .replace("@QNT_TOTAL", (Number(quantidade)+1))
 154:                .replace("@VALOR_TOTAL", vlrTotal)
 155:                .replace("@EMAIL_COMPRADOR", emailComprador)
 156:                .replace("@TELEFONE_COMPRADOR", telefoneComprador)
 157:                .replace("@APELIDO_COMPRADOR", apelidoComprador)
 158:                .replace("@CIDADE_COMPRADOR", cidadeComprador)
 159:                .replace("@ESTADO_COMPRADOR", estadoComprador)
 160:                .replace("@NOME_COMPRADOR", nomeComprador);
 161:                
 162:        bodyElem.innerHTML = emailBody;
 163:        
 164:        //Tenta obter o campo de listagens dos e-mails dos destinatários
 165:        var el = gmail.getActiveViewElement();
 166:        var aTos=evaluateXPath('//textarea[@name="to"]', el);
 167:        if (!aTos || aTos.length<1) {
 168:                window.alert("Erro: não foi possível determinar onde está o campo relativo aos emails do destinatário. Isso pode ocorrer no caso do GMail mudar sua estrutura DHTML.");
 169:                return;
 170:        }
 171:        var to = aTos[0];
 172:        to.value = nomeComprador + "<" + emailComprador + ">";
 173:        
 174:        console.log("Viva Java! Viva a Liberdade! Reviva a SUN!");
 175:}
 176:
 177:function dadosCompra() {
 178:        unsafeWindow.gmonkey.load(GMONKEYVER, _dadosCompra);
 179:}
 180:
 181:GM_registerMenuCommand('Preencher Dados de Compra', dadosCompra); 
 182:

Caso alguém queira o script acima para o Greasemonkey, pode pegá-lo aqui:
Preenchimento automático de e-mail com os dados da compra do cliente do Mercado Livre.

Referências

Labels: ,

0 Comments:

Post a Comment

<< Home