Amigo lector

Se han escrito ríos de tinta sobre la muerte de Google Reader. Una de las mayores víctimas silenciosas, son los usuarios de Blackberry. Hasta el momento, yo usaba la web de iPhone; un vestigio raro ya que hay “app”, pero que era la mar de usable en mi móvil.

De entre todos los reemplazos de Google Reader que se barajan, aún no he encontrado ninguno que me solucione el uso móvil en la Blackberry- no parece haber nadie que tenga una web móvil usable [la de Netvibes ya os digo yo que no se puede usar] y de momento no se huele ninguna aplicación (y por mucho que esto me estigmatice, preferiría no pagar si es necesario [aunque en el caso del lector de feeds, podría hacer una excepción]).

Explorando alternativas, me he puesto un poco en plan hágaselo usted mismo. Feedly dice que implementará Normandy, un clon del backend de Google Reader y de momento apostaré por esta reimplementación. De hecho, Google Reader no tiene API “oficial”, pero mucha gente la ha destripado y documentado, y de hecho goza de cierta popularidad. Así pues, me he puesto a buscar librerías que implementen la API.

Dado que uno trabaja mayoritariamente Python/Django y Java, esto me ha limitado un poco la búsqueda. Para Java, el mejor candidato parece greader-unofficial, pero parece estar un poco muerto con tan solo 47 commits en su repositorio, el último de octubre de 2011. En cambio, naturalmente parece que para Python existe libgreader, con commits de anteayer y con mucha mejor pinta.

Así pues me he puesto manos a la obra y he iniciado un proyecto Django publicado en Github, GROLM (Google Reader on Lightweight Mobile). Es un proyecto Django 1.5 estándar sobre una base de datos PostgreSQL.

libgreader proporciona cuatro alternativas a la hora de manejar la autenticación contra Google Reader:

  • proporcionarle el usuario/contraseña de la cuenta Google y que él mismo autentique
  • OAuth
  • OAuth2
  • una variante de OAuth para Google App Engine

; obviamente la menos usable y/o poco segura es la de la contraseña, y tampoco quiero desarrollar sobre App Engine, así que me he decantado por OAuth2 (al ser más moderna obviamente que OAuth). El mecanismo de autenticación de OAuth2 de libgreader parece completo, pero deseaba integrarlo con el sistema de autenticación de Django para ahorrarme faena.

Para ello, he localizado django-social-auth, que integra en el sistema de autenticación de Django diversos mecanismos de login social entre los que se incluye OAuth2. La configuración de django-social-auth con OAuth2 es relativamente sencilla, simplemente tenemos que añadir el siguiente fragmento a nuestro settings.py:

INSTALLED_APPS = (
  # ...
  'social_auth',
)
AUTHENTICATION_BACKENDS = (
  'social_auth.backends.google.GoogleOAuth2Backend',
)
GOOGLE_OAUTH_EXTRA_SCOPE = [
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/userinfo.profile',
  'https://www.google.com/reader/api/',
 ]
LOGIN_URL = '/login/google-oauth2'
LOGIN_REDIRECT_URL = '/logged-in/'
LOGIN_ERROR_URL = '/login-error/'
GOOGLE_OAUTH2_CLIENT_ID = 'xxxx'
GOOGLE_OAUTH2_CLIENT_SECRET = 'xxxx'

, donde los dos últimos parámetros los podemos obtener de la Google API Console (donde también deberemos añadir las URLs de nuestra aplicación para validar el proceso de login)

Con esto, con anotar una vista como @login_required, al visitarla se nos redirigirá a la página de autenticación de las cuentas Google donde haremos login y se nos redirigirá de nuevo a la vista ya autenticados (se creará un usuario de Django correspondiente al usuario de Google y se vinculará a la sesión del usuario).

Finalmente, para “propagar” esta autenticación a libgreader, el mecanismo que he encontrado es extraer el token de acceso que recoge django-social-auth y almacena en una base de datos y pasárselo a libgreader, algo que he encapsulado en un módulo, pero que en realidad es bastante sencillo:

usa = UserSocialAuth.objects.get(user=user)
 auth = OAuth2Method(settings.GOOGLE_OAUTH2_CLIENT_ID, settings.GOOGLE_OAUTH2_CLIENT_SECRET)
 auth.authFromAccessToken(usa.extra_data['access_token'])
reader = GoogleReader(auth)

, donde user es el usuario (que desde una vista podemos obtener por ejemplo haciendo request.user). Una vez tenemos esto, ya obtenemos el objeto GoogleReader que constituye el punto de acceso a la API.

El resto de código implementado por el momento tan sólo obtiene la reading-list (los elementos sin leer) y muestra sus 20 primeras entradas.

Google Apps es de pago

(llego muy tarde a esto, disculpas)

Hace mucho mucho tiempo, Google sacó Google Apps con su edición gratuita. Nos daba una posibilidad de usar las aplicaciones de Google (GMail, Docs [ahora Drive], etc.), bajo un dominio propio y con administración centralizada de usuarios. ¡Y gratis!

Y hubo gran regocijo y cantidad de gente con dominio propio se hizo la cuenta gratuita, migró su correo y demás a Apps (perdiendo datos o con gran trabajo- yo tengo pesadillas de cuando pasé mis estrellitas de Google Reader…) y contempló maravillada la nueva realidad.

Inicialmente, Apps era gratuito hasta 25 usuarios, y a parte de ese límite, las características de la versión de pago no eran tan atractivas (si no recuerdo mal, más espacio, herramientas para migrar correo e integración con directorios, básicamente). Naturalmente, no sólo particulares se hicieron esto sino que empresas (sospecho que muchas) se pasaron a Google Apps.

Puedo entender la frustración que sintieron en Google al comprobar cómo empresas con ingresos para las que tendría todo el sentido del mundo contratar la versión de pago por un coste ínfimo (40€/usuario/año es ridiculo comparado con, pongamos, lo que cuesta el empleado- imaginad como os sentiríais si os aumentasen en 40€ el sueldo bruto anual…), utilizaban la versión gratuita (que Google vendía como para pequeñas asociaciones, familias y otras entidades no precisamente con ánimo de lucro). Obviamente no se trata de nada ilegal, e incluso si pensamos que Google es una empresa enorme con unos beneficios inimaginables, podemos defender que no se trata de algo inmoral siquiera… pero insisto, puedo comprenderles.

Así pues, fueron recortando. La versión gratuita se iba ocultando más y más, luego se redujo el límite de 25 a 10 usuarios y finalmente, se eliminó completamente.

Dos apuntes:

Uno, es posible que las empresas que “abusaron” (insisto en las comillas), hayan hecho que los verdaderos destinatarios del invento lo hayan perdido.

Dos, para los friquis que lo echamos de menos… ¿realmente aporta tanto? Lo más visible es el dominio personalizado para los emails, pero con las opciones de accounts y forwarding, se puede simular bastante bien con el GMail tradicional. La gestión centralizada de usuarios… vaya, si la necesitas es porque tienes bastantes usuarios (probablemente, más de 25).

Apuntes sobre Dart

Google ha sacado hoy Dart.

El apunte rápido (que seguro que otros mejoran) es que es un verdadero Javascript. Es un lenguaje muy muy Java que compila a Javascript. Las diferencias con Java van por dos lados:

  • Adecuaciones para funcionar bien cuando se compila a Javascript- i.e. no hay threads, hay “isolates”, etc.
  • Esas mejoras puntuales de Java que llevamos pidiendo a gritos desde hace siglos

Las mejoras de Java son de ovación cerrada:

  • Las clases en Dart generan un interfaz equivalente a su parte pública
  • Constructores con inicializadores concisos
  • Declaraciones anónimas y concisas de funciones
  • getters y setters transparentes. De bonus, se integran con los interfaces
  • Literales para listas y mapas
  • “==” es equals y “===” es “==”. Ver “===” me produce grima por traumas varios, pero creo que es la solución correcta.
Siendo realistas, cubre la mayoría de “defectos” “resolubles” de Java. No, no tiene inferencia de tipos, ni lambdas con excepciones chulas, ni “final” por defecto… y quizás no es todo como uno lo había soñado, pero es una solución práctica y disponible hoy.
Eso es lo positivo. En lo negativo, el tipado opcional me escama- y me duele que signifique sacrificios (hay ahí una cosilla un poco rara con las funciones que no devuelven valor que me deja intranquilo). Me queda la curiosidad de estudiar los isolates para saber si aportan algo o si son sencillamente la manera correcta de montar concurrencia en código que será compilado a Javascript y ejecutado por los motores de Javascript existentes.
He visto otras cosas que aún no me he mirado a fondo que no sé dónde colocar: soporte en el lenguaje para factorías, “const” el sistema de librerías y que null sea un objeto; es difícil saber si serán cosas buenas o malas.
En fin, cosas interesantes. No parece, sin embargo, que Dart aspire de momento a ser algo más que un sustituto de Javascript (algo que no me interesa mucho- el principal problema de Javascript no es el lenguaje en sí, en mi opinión)… con lo que para mi, no es muy interesante de momento.  Si algún día se planta como una alternativa para desarrollo de aplicaciones y para programación, tiene  la oportunidad de ser Java++, pero sin añadir la complejidad y cerradez de C#… pero ni siquiera sé si Google pretende que lo sea (ese rol lo quieren para… ¿Go? ¿Dart? ¿Java? ¿Python?) .

Tecnocracia china

Tras más de 300.000 entradas de RSS leídas, he decidido migrar mis datos de Google Reader de @gmail.com a mi cuenta de Google Apps.

A parte de sacrificar tan bonito número y perder un buen montón de datos, migrar las estrellas y elementos compartidos es duro (2500+ pulsaciones de shift+s, k lo atestiguan).

Mejoras en Google Docs

Es bien conocida mi afición por las hojas de cálculo- esa herramienta de programación funcional frecuentemente mal empleada como base de datos que es fácilmente comprensible.

Así pues, celebro profundamente las mejoras introducidas por Google recientemente en la hoja de cálculo de Google Docs. Si aún no le habéis dado al botón de nueva versión (arriba, al lado de vuestro usuario)- la gran ventaja para mí es que ya no tenemos que editar y visualizar las fórmulas de las celdas en la misma celda (lo cual era harto incómodo, ya que el espacio era extremadamente reducido), sino que disponemos de un cuadro dedicado en la barra de herramientas como en el Excel.