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...
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.
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
.
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 dê 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 só 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> Td blz?<br><br></div><span style="color: rgb(0, 102, 0);"> É 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ê tá 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> É 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
- Dive Into Greasemonkey
- Gmail API for Greasemonkey
- gmail-greasemonkey: Gmail Greasemonkey Scripts
- Gecko DOM Reference: document.evaluate
- Regular Expression Examples: Negated string: Donal Fellows (Special Thanks! I was breaking my head.. before to find your snippet regex)