Categorias
Tecnologia

Lendo RSS Feed somente com Javascript (jQuery)

Eu construi uma página estática em HTML, CSS e JS para ser uma espécie de portfólio e cartão pessoal para mim e queria colocar uma seção com os artigos deste blog nela. A melhor maneira de acessar esses artigos sem muito esforço é usando o RSS Feed do blog.

Mas a página é “estática”, então eu poderia usar no máximo o Javascript para ler o Feed do blog. Uma opção seria acessá-lo via Ajax e processar os dados em seguida, mas se o Feed for de outra origem (domínio diferente, que não era o meu caso, mas pode ser o seu) ia acabar esbarrando em um erro de segurança (CORS Error) e não funcionaria.

Então encontrei uma solução (no link de referência no final do artigo), usar uma API do Google que lê um Feed e retorna um JSON com as informações dele.

Segue abaixo uma versão do código que estou utilizando na página, totalmente comentado.

[gist id=”98d6f630b9b89b229deaa19acb38e2bd”]

Os items que temos disponíveis para acesso, como mostra a imagem abaixo, são o autor, categorias e tags, o conteúdo inteiro em HTML, um pequeno snippet do conteúdo em texto puro, a URL do artigo, a data de publicação e o título. Eu senti falta do retorno das mídias, como fotos, por exemplo, mas se for necessário a opção seria pegá-las do próprio HTML que retorna em “content“.

É isso aí, qualquer dúvida ou sugestão deixe nos comentários abaixo. Para ver esse código em funcionamento acesse o site.

Referência: http://pt.stackoverflow.com/a/65758

Categorias
Tecnologia

Usando Grunt para compilar SCSS (Sass)

O Grunt é um gerenciador de tarefas JavaScript. O conheci pela primeira vez quando utilizei o Yeoman para desenvolver um projeto em AngularJS (leia mais).

O Sass é uma linguagem de extensão de CSS, que se auto-intitula “CSS com superpoderes”.

Precisei começar um novo projeto de frontend montando apenas os HTMLs, JavaScripts e CSSs das páginas. Então resolvi conhecer melhor o Grunt e o Sass.

Percebi que dominar essas ferramentas gera dezenas de possibilidades novas para o desenvolvimento frontend. Claro que ainda não dominei, mas vou escrever um pouco sobre o que já aprendi.

Obs: Para todos os comandos abaixo estou utilizando a linha de comando (console) do Linux.

Para instalar o Sass é necessário o package manager do Ruby, o RubyGems.

sudo su -c "gem install sass"

Para instalar o grunt-cli é necessário o package manager do Node.js, o npm. Aproveito para já instalar os pacotes que vou utilizar: grunt-contrib-sass e grunt-contrib-watch.

npm install grunt grunt-contrib-sass grunt-contrib-watch

Estou usando o Bootstrap nesse projeto, então é necessário instalar o bootstrap-sass pelo npm.

npm install boostrap-saas

Minha estrutura de diretórios será a seguinte:

  • project/
    • node_modules/
    • public/
      • css/
      • img/
      • js/
      • index.html
    • sass/
      • style.scss
    • Gruntfile.js
    • package.json

No arquivo Gruntfile.js configuramos todas as tarefas que o Grunt vai executar. No caso desta publicação faremos a preprocessamento do SCSS para CSS.

Todas as tarefas do Grunt são executadas na linha de comando (console) precedidas por “grunt”, como por exemplo “grunt watch” ou “grunt build”.

[gist id=”f1c4801d3fd6f07a76ac28ec4ef3d4d6″]

Primeiro configurei o Sass para compilar para o ambiente de desenvolvimento, nesse caso o CSS não ficará comprimido, para que eu possa vê-lo em ação. No caso da configuração para ambiente de produção ele será comprimido.

Então configuro a tarefa do grunt-watch, ela acionará a tarefa “sass:dev“, que configuramos no passo anterior, a cada mudança que eu fizer aos arquivos *.scss. Isso serve para que eu não precise rodar um comando grunt manualmente a cada alteração no SCSS, o que seria contraproducente.

Obs: Para que isso aconteça é preciso deixar o comando “grunt watch” rodando na linha de comando (console).

No final do arquivo registro as tarefas com o registerTask. No caso apenas “grunt build“, que será usado para gerar o CSS final comprimido para produção, pois a tarefa que gera os arquivos não-comprimidos para ambiente de desenvolvimento já será chamada pelo grunt-watch e não precisa ser registrada novamente.

Estas tarefas registradas ao final do arquivo servem para agregar várias tarefas a um único comando. Assim quando você precisar rodar tudo de uma vez para gerar a versão de produção, você rodorá apenas “grunt build” e todas as tarefas da lista serão executadas. No nosso caso temos apenas o Sass por enquanto, mas futuramente podemos ter diversas tarefas a serem executadas para gerar os arquivos de prod.

Vou falar mais sobre Grunt e Sass no futuro. Se tiver alguma sugestão ou dúvida sobre o conteúdo desta publicação, dexe um comentário abaixo.

Categorias
Tecnologia

Autenticação do Mandrill Webhook com Python Flask

Mandrill é um serviço para disparo de emails transacionais, ele possui relatórios e você pode receber os eventos de cada mensagem (enviado, aberto, click em link, etc) enviada via Webhook.

Procurando uma forma de autenticar o Webhook do Mandrill com Python, o qual eu já havia feito com PHP, eu encontrei esse artigo que mostrava como fazer utilizando o framework Webapp2 e usando uma versão 2.7 do Python. Como eu utilizo Flask com Python 3.4, tive que fazer algumas modificações, mas consegui fazer funcionar.

Segue o trecho de código que estou utilizando:

def calc_mandrill_signature(raw, key):
    import hashlib
    import hmac
    import base64

    digest = hmac.new(key.encode('utf-8'), raw.encode('utf-8'), hashlib.sha1).digest()
    hashed = base64.encodestring(digest).decode("utf-8").rstrip('\n')
    return hashed

def verify_mandrill_signature(request):
    '''
    Mandrill includes an additional HTTP header with webhook POST requests,
        X-Mandrill-Signature, which will contain the signature for the request.
        To verify a webhook request, generate a signature using the same key
        that Mandrill uses and compare that to the value of the
        X-Mandrill-Signature header.
    :return: True if verified valid
    '''
    mandrill_signature = request.headers['X-Mandrill-Signature']
    mandrill_key = 'aqui vai a API key do seu webhook'
    signed_data = request.url
    sorted_key = sorted(request.form)
    for k in sorted_key:
        signed_data += k
        signed_data += request.form[k]
    expected_signature = calc_mandrill_signature(signed_data, mandrill_key)
    return expected_signature == mandrill_signature

@app.route('/webhook', methods=['POST'])
def event_webhook():
    if not verify_mandrill_signature(request):
        abort(403)

    import json
    data = json.loads(request.form['mandrill_events'])

    for e in data:
        '''
        Insira o que você quiser fazer com os resultados dos eventos...
        '''
Categorias
Tecnologia

Estruturando aplicações maiores com o microframework Flask

A principal vantagem de se utilizar um microframework para criar um sistema web é a pouca quantidade de “regras” que se precisa seguir no desenvolvimento. O que quero dizer é que se ganha liberdade para escolher o que e como utilizar as facilidades que o framework provém.

Com o advento da liberdade vem a pergunta: qual é o melhor jeito de fazer?

Como de costume, assim que comecei a utilizar o microframework Flask, escrito em Python, segui diversos tutoriais que encontrei na internet para dar os primeiros passos. Fiz alguns sistemas pequenos para aprender e logo vieram as dúvidas. Pesquisando mais e mais percebi que existem diversas maneiras de se estruturar uma aplicação com ele.

E a lição mais interessante que tirei com tudo isso é que deve-se criar seu próprio jeito de fazer as coisas. De acordo com seu background e com seu conhecimento anterior o desenvolvedor vai naturalmente criando seu “estilo” de estruturar seu código e seus sistemas como um todo.

Criando pequenos sistemas não se tem dificuldades com a estrutura, mas a partir do momento que o sistema cresce a coisa muda de figura. Quase todos os tutoriais estilo “hello world” em Flask tem o mesmo formato: um arquivo único que possui todas as chamadas e roda o sistema, como no exemplo abaixo.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

É claro que para criar um sistema mais complexo colocar tudo em um arquivo único é uma péssima ideia. Mas esse tipo de exemplo serve para dar a noção de como o framework é simples.

Mas como estruturar um sistema maior? Nesse caso se cria o arquivo que contém as rotas e suas funções, um arquivo que carrega o aplicativo e um arquivo com o mapeamento do banco de dados. Uma estrutura de diretórios mais ou menos como no exemplo abaixo.

/app
 __init__.py
 models.py
 views.py
/run.py

Até aí tudo bem, ainda se tem uma aplicação bem simples. Adicionamos os diretórios de templates, de arquivos estáticos e o arquivo com as configurações e teremos a estrutura padrão de um sistema simples em Flask.

/app
 /static
 /templates
 __init__.py
 models.py
 views.py
/config.py
/run.py

Ficou um pouquinho mais complexo, mas ainda segue o padrão de tutoriais básicos de utilização do Flask.

Nesse caso, todas as rotas que o sistema terá ficarão em apenas um único arquivo. Pode-se imaginar que isso não é uma boa ideia no caso de sistemas mais complexos, correto?

Basta imaginar a quantidade de linhas que o arquivo views.py pode atingir… a manutenção e o entendimento dele ficarão mais difíceis. Sabe-se que, principalmente para scripts Python, isso não é a melhor opção, pois a ideia é que o código seja simples e legível.

É aí que entram os Blueprints.

Blueprints

Existem diversas formas de utilizar Blueprints no Flask, mas eu basicamente tenho utilizado como aprendi com um vídeo de Miguel Grinberg para a PyCon 2014 (se não me engano): uma forma de separar e modularizar as rotas do aplicativo.

Funciona da seguinte maneira. Em vez de termos um arquivo para todas as rotas do sistema, modularizamos as rotas utilizando arquivos separados e registrando Blueprints para cada um deles.

Em uma tradução livre da documentação do Flask:

Um Blueprint funciona de forma parecida com o objeto de aplicação do Flask, mas não é a mesma coisa. Poderiam ser criadas várias aplicações separadas, mas elas não compartilhariam as mesmas configurações e seriam tratadas na camada WSGI e não na camada do Flask. Já os Blueprints compartilham as mesmas configurações e são uma forma de separar funções dentro da mesma aplicação.

Como eu uso os Blueprints

Para cada módulo que defino no sistema eu crio um arquivo e registro seu Blueprint, como no exemplo abaixo, que simula o arquivo meumodulo.py.

from flask import Blueprint, render_template

meumodulo = Blueprint('meumodulo', __name__, template_folder='templates')

@meumodulo.route('/')
def index(page):
    return render_template('index.html')

Dessa maneira eu crio todas as rotas desse “módulo” específico. Para registrar o Blueprint é preciso adicionar a linha abaixo no arquivo __init__.py, depois de inicializar o objeto app do Flask.

from .meumodulo import meumodulo
app.register_blueprint(meumodulo)

Se quiser que o novo módulo tenha um prefixo para todas as suas rotas, basta adicionar url_prefixao registro do Blueprint.

app.register_blueprint(meumodulo, url_prefix='/modulo')

Já começamos a deixar tudo mais organizado, pelo menos no que diz respeito às rotas. E com isso podemos ter a seguinte estrutura de diretórios.

/app
 /static
 /templates
 __init__.py
 meumodulo.py
 models.py
 outromodulo.py
/config.py
/run.py

Evitando dependências circulares

Para evitar dependências circulares, podemos criar uma função que registre os Blueprints e a chamamos ao final do arquivo __init__.py, como mostra o exemplo abaixo.

def register_blueprints(app):
    from .meumodulo import meumodulo
    from .outromodulo import outromodulo
    app.register_blueprint(meumodulo, url_prefix='/modulo')
    app.register_blueprint(outromodulo, url_prefix='/outromodulo')

register_blueprints(app)

Conclusão

Depois de tudo isso, ainda utilizo uma extensão do Flask chamada Flask-Script para criar um arquivo manager.py no lugar do arquivo run.py. Mas vou explicar melhor sobre isso em uma post futuro.

Essas são apenas algumas dicas que mostram como eu tenho utilizado o microframework Flask para alguns dos meus projetos. Sou relativamente novo com Python e com Flask e por isso tenho certeza de que no futuro terei descoberto novas formas de estruturar os sistemas maiores que farei, mas por enquanto essas são as dicas que tenho para dar para quem se encontra na mesma situação de estudante que eu. Espero poder ter ajudado.

Qualquer dúvida ou sugestão, por favor deixe seu comentário abaixo que responderei sempre que possível.

Atá a próxima.

Categorias
Tecnologia

Summernote, um editor WYSIWYG super simples para Bootstrap

O Summernote é um editor WYSIWYG muito bom, e simples, para utilizar em aplicações web. Pra quem não sabe o que significa WYSIWYG, vejamos o que nos diz a Wikipedia.

WYSIWYG é o acrônimo da expressão em inglês “What You See Is What You Get”, cuja tradução remete a algo como “O que você vê é o que você obtém” (OQVVEOQVO). Significa a capacidade de um programa de computador de permitir que um documento, enquanto manipulado na tela, tenha a mesma aparência de sua utilização (…)

No nosso caso, estamos falando de aplicações web. O Summernote é um dos editores mais simples que já encontrei e sua instalação foi tão fácil que me surpreendi. Até mesmo para personalizar o upload de imagem foi mais simples do que eu imaginava.

Outros editores WYSIWYG para web muito conhecidos, e que eu já utilizei em alguns projetos, são o CKEditor e o TinyMCE. Apesar de suas instalações não serem complicadas, ambos tem muitos arquivos e exigem um conhecimento mais específico para executar qualquer alteração, principalmente no upload de imagens.

Para utilizar o Summernote é preciso jQuery, Bootstrap e Font Awesome (para os ícones). Com as linhas abaixo você consegue essas dependências funcionando na sua aplicação.

<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.1/js/bootstrap.min.js"></script>
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet">

A seguir, basta inserir o CSS e o código JavaScript do Summernote.

<link href="summernote.css" rel="stylesheet">
<script src="summernote.min.js"></script>

Então basta escolher qual é o campo que você deseja transformar em um editor WYSIWYG, adicionar o código de inicialização do Summernote, como no exemplo abaixo, e voilà!

<div id="summernote">Hello Summernote</div>
<script>
$(document).ready(function() {
  $('#summernote').summernote();
});
</script>

Seu campo vai aparecer dessa maneira:

Se você quer personalizar os itens da barra do editor, o tamanho do campo, entre outras coisas, basta ver as features no site do Summernote.

Personalizando o upload de imagens

Ao inserir uma imagem, por padrão, o editor insere os dados da imagem em Base64 ao texto. Mas normalmente não é isso que queremos no nosso código, certo? Então a opção é alterar o padrão para efetuar um upload do arquivo ao ser inserido.

Não vou abordar aqui o script backend por trás do upload, porque isso não tem nada a ver com o editor em questão, vou mostrar apenas como chamamos esse código pelo Summernote.

$(document).ready(function() {
    $('#summernote').summernote({
        onImageUpload: function(files, editor, welEditable) {
            sendFile(files[0],editor,welEditable);
        }
    });
});

function sendFile(file,editor,welEditable) {
    data = new FormData();
    data.append("file", file);
    $.ajax({
        data: data,
        type: "POST",
        url: "url/para/upload/",
        cache: false,
        contentType: false,
        processData: false,
        success: function(url) {
            editor.insertImage(welEditable, url);
        }
    });
}

Primeiro configuramos o callback onImageUpload para chamar nossa função de envio de arquivo. Essa função, a sendFile, cria um novo objeto de formulário pelo javascript e insere o nosso arquivo a ele. Com o método $.ajax do jQuery chamamos nosso script de backend e, mais uma vez, voilà!

Funcionou muito bem pra mim e espero que essas dicas possam ajudar a facilitar a vida de mais pessoas por ai.