Archivo

Entradas Etiquetadas ‘facebook’

Automatizando la publicación de nuestras páginas de Facebook

Lunes, 6 de Febrero de 2012 Gaspar Fernández Sin comentarios

facebook_1
Si administramos páginas de Facebook, en ocasiones nos interesa introducir contenidos procedentes de diversas fuentes, tal vez un RSS (o varios) (Por ejemplo, si administras la página de un blog, o quieres mostrar noticias), eso sí, de fuentes confiables. O tal vez quieres publicar un mensajes varias veces a lo largo de un día, o varios mensajes de forma escalonada en el tiempo.

Objetivos

El problema es que esto nos obliga a estar constantemente pendientes de esas publicaciones. En mi caso, cuando tengo tiempo, sí puedo entrar en mis páginas de Facebook para hacer publicaciones, pero me gustaría que esas publicaciones también fueran aprovechables para mis visitantes en Hispanoamérica, cuyos horarios son muy diferentes a los míos, así como para gente que suele conectar más por la mañana o por la tarde. Además, en ocasiones me interesa publicar varios mensajes en alguna de las páginas, pero quiero ver antes la reacción que tienen entre los usuarios (Comentarios y Me Gusta), sin ser demasiado pesado (cuando veo muchas publicaciones seguidas de una misma fuente me agobio y siento la tentación de dejar de recibir publicaciones de esa fuente).

Para solucionarlo, propongo montar una aplicación web (lo que muestro aquí es sólo un esbozo, ya que podemos hacerla tan compleja como queramos), para montar esta aplicación, aprovecharé información que ya he puesto en algún post anterior.

Mi objetivo es poder administrar todas mis páginas de Facebook desde un sitio centralizado, sin tener que entrar una a una modificando las publicaciones.

Base de datos de la aplicación

Como hemos visto en el post anterior, para publicar en nombre de una página, debemos almacenar los access tokens que dan permiso a la aplicación para publicar como si fuera esa página de Facebook. Además, debemos almacenar los IDs de páginas de Facebook para que la aplicación sepa quién va a publicar y dónde (en el muro de dicha página)

Para ello voy a utilizar el motor MySQL y así podremos subir la aplicación a cualquier hosting que soporte este motor. En la base de datos (facebook_autopublish), crearemos varias tablas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CREATE TABLE `facebook_autopublish`.`paginas` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 128 ) NOT NULL ,
`access_token` VARCHAR( 255 ) NOT NULL ,
`category` VARCHAR( 64 ) NOT NULL ,
`fcbkId` VARCHAR( 32 ) NOT NULL ,
`last_update` BIGINT NOT NULL
) ENGINE = InnoDB;

ALTER TABLE `paginas` ADD INDEX ( `last_update` ) ;

CREATE TABLE `facebook_autopublish`.`publish` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`pageID` INT UNSIGNED NOT NULL ,
`time` BIGINT NOT NULL ,
`message` TEXT NOT NULL ,
PRIMARY KEY ( `id` ) ,
INDEX ( `id` )
) ENGINE = InnoDB;

ALTER TABLE publish ADD FOREIGN KEY ( pageID ) REFERENCES paginas( id ) ;

La tabla paginas contendrá lo siguiente:

  • id : identificador de la página para la aplicación que estamos desarrollando
  • name : nombre de la página, obtenido de Facebook
  • access_token : access_token de la página, obtenido de Facebook
  • category : categoría de la página, obtenida de Facebook
  • fcbkId : ID de la página en Facebook, nos servirá para saber dónde publicar
  • last_update : momento en el tiempo de nuestra última publicación en la página

La tabla publish contendrá lo siguiente:

  • id : Identificador de la publicación para la aplicación
  • pageID : Id de la página donde se va a publicar
  • time : Momento en el tiempo en que queremos publicar
  • message : Texto de la publicación

La primera tabla (paginas), se generará automáticamente al cargar la página de identificación en Facebook. Para la segunda tabla (publish), debemos crear un interfaz web o CLI que vaya introduciendo los mensajes que tenemos que ir publicando. Ese interfaz no lo voy a incluir en este ejemplo, podemos incluso hacerlo desde PHPMyAdmin, o desde el comando mysql.

Script de identificación

Este script contendrá la autorización de la aplicación, y el llenado de la tabla paginas con los datos extraídos de Facebook (los ID de página y los access_tokens son lo más importante), y tenemos que almacenarlos en base de datos, para ello podemos usar el siguiente script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php

$mysql_host = 'Host Mysql';
$mysql_user = 'Usuario MySQL';
$mysql_pass = 'Pass MySQL';
$mysql_db   = 'facebook_autopublish';

$api_key = 'API Key';
$api_sec = 'API Secret';

require_once('facebook_ext.php');
// Definimos constantes
define(NEEDED_PERMISSIONS,  'publish_stream,offline_access,manage_pages');
define('_scampo', '`');
define('_svalor', '\'');

// Definimos códigos de error
define(NOT_INSTALLED,      1);
define(NO_PERMISSIONS,     2);
define(NO_MYSQL_CONN,      3);
define(NO_PAGE_DATA,       4);
define(MALFORMED_ARRAY,   90);

// Funciones para el manejo de la bdd
function escapa($dato, $char, $numeric=true)
{
  if (($numeric) && (is_numeric($dato)))
    return ($dato+0);       /* Si es 0, no devolverá FALSE */
  else
    return $char.mysql_real_escape_string($dato).$char;
}

function valor($valor, $numeric=true)
{
  return escapa($valor, _svalor, $numeric);
}

function campo($valor, $numeric=true)
{
  return escapa($valor, _scampo, $numeric);
}

function insert($tabla, $datos)
{
  $uso='
INSERT';

  $sql=$uso.'
INTO '.campo($tabla). '(';
  $values='
VALUES (';

  $campos=array_keys($datos);
  $ndatos=count($campos);
 
  for ($i=0; $i<$ndatos; $i++)
    {
      $campo=$campos[$i];
      if ($i)
    {
      $sql.=", ";
      $values.=", ";
    }

      $valor = $datos[$campo];
      $sql.=campo($campo);
      $values.= valor($valor);
    }
  $values.=")";
  $sql.=") ".$values.";";

  $res = mysql_query($sql);
  // Depuración
  echo "Ejecutando: ".$sql.'
<br/>';
  return ($res)?mysql_insert_id():false; /* Devolver el ID del elemento insertado */
}

function truncate($table)
{
  return mysql_query("TRUNCATE TABLE ".campo($table));
}

try
{
  if (!mysql_connect($mysql_host, $mysql_user, $mysql_pass))
    throw new Exception('
No puedo conectar con el servidor MySQL', NO_MYSQL_CONN);

  // Generar otra excepción por si las moscas.
  mysql_select_db($mysql_db);

  $facebook = new FacebookExtended(array(  
                     '
appId'  => $api_key,
                     '
secret' => $api_sec,
                     '
cookie' => true ,
                       ));

 
  $sesion = $facebook->getUser();
  if (!$sesion)
    throw new Exception('
Aplicación no instalada', NOT_INSTALLED);

  echo "Estamos identificados en Facebook<br/>";
  echo "Usuario: ".$sesion."<br/>";

  $permissions = $facebook->askForPermissions(NEEDED_PERMISSIONS);
   
  if (!$permissions)
    throw new Exception('
No tengo permisos suficientes', NO_PERMISSIONS);
 
  $pagedata=$facebook->api('
/me/accounts');

  if ( (!$pagedata) || (!isset($pagedata['
data'])) || (count($pagedata['data'])==0) )
    throw new Exception('
No he recibido información de páginas', NO_PAGE_DATA);

  truncate('
paginas');

  $npages = count ($pagedata['
data']);
  for ($i=0; $i<$npages; $i++)
    {
      $pdata=$pagedata['
data'][$i];
      // Depuración
      echo "Insertando pagina: ".$pdata['
name']."<br/>";

      if (!insert('
paginas', array('name'         => $pdata['name'],
                   '
access_token' => $pdata['access_token'],
                   '
category'     => $pdata['category'],
                   '
fcbkId'       => $pdata['id'],
                   '
last_update'  => 0)) )
    echo mysql_error()."<br/>";
    }

}
catch (FacebookException $e)
{
  echo "Error de Facebook: ".$e->getCode().": ".$e->getMessage();
}
catch (Exception $e)
{
  switch ($e->getCode())
    {
    case NOT_INSTALLED:
      $facebook->loginUser();
      break;
    case NO_PERMISSIONS:
      $facebook->loginUser(NEEDED_PERMISSIONS);
      break;

    default:
      echo "Ocurrió un error: ".$e->getMessage();
    }
}
?>

Publicando mensajes automáticamente

Ahora, sólo tenemos que ir insertando entradas dentro de la tabla publish, especificando el momento en el que se va a insertar en el campo time y el ID de la página donde se va a insertar (ID dentro de la aplicación, no dentro de Facebook, se puede mirar en la tabla paginas)

Asimismo la aplicación buscará mensajes nuevos para publicar y que no haga menos de dos horas (configurable) desde el último mensaje publicado en la página especificada. Para ello tenemos el siguiente código (publica.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php

$mysql_host = 'MySQL Host';
$mysql_user = 'MySQL User';
$mysql_pass = 'Password';
$mysql_db   = 'facebook_autopublish';

$api_key = 'xxxxxxxxxxxx';
$api_sec = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

require_once('facebook_ext.php');

// Definimos constantes
// Tiempo mínimo entre publicaciones, 7200 segundos = 2h
define(MIN_TIME_BET_PUB,   7200);

// Definimos códigos de error
define(NOT_INSTALLED,      1);
define(NO_PERMISSIONS,     2);
define(MALFORMED_ARRAY,   90);
define(BAD_MYSQL,          3);

try
{
  if (!mysql_connect($mysql_host, $mysql_user, $mysql_pass))
    throw new Exception('No puedo conectar con el servidor MySQL', NO_MYSQL_CONN);

  // Generar otra excepción por si las moscas.
  mysql_select_db($mysql_db);
 
  $campos='paginas.id as pID, publish.id as pubId, paginas.fcbkId, paginas.access_token, publish.message';

  $sql='SELECT '.$campos.' FROM `publish` LEFT JOIN `paginas` ON publish.pageID=paginas.id WHERE last_update<'.(time()-MIN_TIME_BET_PUB).' ORDER BY last_update ASC LIMIT 1';
  $res=mysql_query($sql);
  if (!$res)
    throw new Exception('Hubo un error en la sentencia MySQL ('.$sql.'): '.mysql_error(), BAD_MYSQL);

  // Si se ha devuelto algo...
  if (mysql_num_rows($res)>0)
    {
      $data = mysql_fetch_assoc($res);

      $facebook = new FacebookExtended(array(  
                         'appId'  => $api_key,
                         'secret' => $api_sec,
                         'cookie' => true ,
                           ));

      $destino=$data['fcbkId'];
      $access_token=$data['access_token'];
      $public=$data['message'];

      print_r( $facebook->api('/'.$destino.'/feed', 'post', array('access_token' => $access_token,
                                  // 'uid' => $destino,
                                  'message' => $public)));  

      $sql = 'UPDATE paginas SET last_update='.time().' WHERE id=1';
      mysql_query($sql);

    }
} catch (Exception $e)
{
  echo "Ocurrió un error: ".$e->getMessage();
}
?>

Ejecutándolo en el tiempo

El objetivo de estos scripts es poder ejecutarlos cada cierto tiempo y, si usamos un sistema UNIX podemos hacer que cada cierto tiempo (cada 2h, por ejemplo), se haga una petición a la página, para ver si tenemos mensajes nuevos pendientes de publicación, y si hay, que los publique (publica.php ya se encarga de eso).

Para añadir el programa en nuestro cron, debemos ejecutar en un terminal:

$ crontab -e

Y allí escribir lo siguiente:

15 */2 * * * wget http://dominio.xxx/carpeta/publica.php

Donde cambiamos la dirección especificada por la dirección donde hemos instalado el script publica.php. Esto hará que se ejecute cada 2h en el minuto 15, todos los días, todos los meses y todos los días de la semana.

Consideraciones de seguridad

Es una buena idea hacer que index.php sólo podamos ejecutarlo nosotros desde nuestra sesión de Facebook, restringiendo la ejecución a nuestro ID de usuario. Así evitamos que la base de datos se pueble con páginas que no queremos, y también estaría bien restringir esa página con contraseña desde Apache, así evitamos sorpresas.

También es conveniente no hacer TRUNCATE TABLE todo el rato, sino ver y comprobar que los access_tokens no cambian (lo dejamos así, porque en ocasiones, Facebook los ha cambiado, reiniciado, o éstos han caducado pasados unos meses).

En la parte de publica.php sería conveniente el envío de una contraseña, para que no pueda publicar cualquiera, ya sea en una petición POST, GET, o enviándola por SSL. Así evitamos que cualquiera ejecute publica.php , sólo nosotros.

Publicando en Facebook como página para mantener a nuestros fans

Lunes, 30 de Enero de 2012 Gaspar Fernández Sin comentarios

poesiabinaria

Si administras una página de Facebook, esto te interesa, ya que puedes gestionar las publicaciones de forma automática, por ejemplo, si tienes muchas cosas que publicar y quieres hacerlo de manera escalonada, para no hacerlo todo seguido y mantener alerta a tus seguidores.

Para poder poner en práctica todo esto, te recomiendo leer estos artículos anteriores:

Estudiando el tema

El problema de administrar páginas, es que tienes que estar identificado como estas, y además, hacerlo en modo offline. Por otra parte, las páginas tienen sus administradores y éstos son los usuarios que se pueden identificar en aplicaciones.
Facebook hace todo esto a través de palabras de acceso (access tokens), cuando un usuario se identifica en una aplicación se genera un token único para ese usuario y éste durará un tiempo, durante ese tiempo, la aplicación podrá realizar las acciones que el usuario le ha dado permiso para hacer.

En el caso de las páginas, debemos generar un access token que valga para la página en cuestión que queremos manejar. Ese access token debemos pasárselo a la llamada a la API para publicar.

Obteniendo los access tokens de las páginas que administro

Para ello hay que hacer la llamada a la API /me/accounts, con lo que obtendremos un listado completo de las páginas que administramos, ID de páginas (para poder realizar las publicaciones) y los access tokens necesarios para publicar en nombre de esas páginas.

Podemos modificar el programa que teníamos para identificarnos (index.php) de la siguiente manera (facebook_ext está para descarga en un post anterior):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php

$api_key = 'xxxxxxxxxxx';
$api_sec = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

require_once('facebook_ext.php');
// Definimos constantes
define(NEEDED_PERMISSIONS,  'publish_stream,offline_access,manage_pages');

// Definimos códigos de error
define(NOT_INSTALLED,      1);
define(NO_PERMISSIONS,     2);

$facebook = new FacebookExtended(array(  
                       'appId'  => $api_key,
                       'secret' => $api_sec,
                       'cookie' => true ,
                     ));

try
{
 
  $sesion = $facebook->getUser();
  if (!$sesion)
    throw new Exception('Aplicación no instalada', NOT_INSTALLED);

  echo "Estamos identificados en Facebook<br/>";
  echo "Usuario: ".$sesion."<br/>";

  $permissions = $facebook->askForPermissions(NEEDED_PERMISSIONS);
   
  if (!$permissions)
    throw new Exception('No tengo permisos suficientes', NO_PERMISSIONS);
 
  print_r($facebook->api('/me/accounts'));
}
catch (FacebookException $e)
{
  echo "Error de Facebook: ".$e->getCode().": ".$e->getMessage();
}
catch (Exception $e)
{
  switch ($e->getCode())
    {
    case NOT_INSTALLED:
      $facebook->loginUser();
      break;
    case NO_PERMISSIONS:
      $facebook->loginUser(NEEDED_PERMISSIONS);
      break;

    case MALFORMED_ARRAY:
      echo $e->getMessage();
      break;

    default:
      echo "Ocurrió un error no identificado";
    }
}
?>

Con este código, pediremos permiso para administrar páginas, para uso offline y para publicar mensajes en nombre del usuario. Cuando estemos identificados, nos devolverá un array con los nombres de las páginas, los ID y los access tokens. El array dentrá la siguiente forma:

Array
(
[data] => Array
(
[0] => Array
(
[name] => Nombre de página 1
[access_token] => xxxxxxx
[category] => Website
[id] => 123456789
)

[1] => Array
(
[name] => Nombre de página 2
[access_token] => xxxxxxx2
[category] => Website
[id] => 987654321
)
………………..
[n] => Array
(
[name] => Nombre de página N
[access_token] => xxxxxxxn
[category] => Website
[id] => 918273645
)
)
)

Se mostrarán todas las páginas que administramos. Ahora tendremos que anotar el ID de la página con la que queremos publicar y el access token para copiarlos en el código del programa encargado de publicar.

Publicando como si fuéramos una página de Facebook

Para hacer la publicación tenemos que hacer una llamada a /ID_de_página/feed especificando el access token con el que queremos publicar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

$api_key = 'xxxxxxxxxxx';
$api_sec = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

require_once('facebook_ext.php');

$facebook = new FacebookExtended(array(  
                       'appId'  => $api_key,
                       'secret' => $api_sec,
                       'cookie' => true ,
                     ));

try
{
  // ID de la página que queremos editar. La podemos ver en la URL de Facebook de la página
  $destino=189639191053576;
  $access_token='XXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  $public='Probando mensajes automáticos con el modo offline';

  print_r( $facebook->api('/'.$destino.'/feed', 'post', array('access_token' => $access_token,
                                  'message' => $public)));  
} catch (Exception $e)
{
  echo "Ocurrió un error";
}
?>

Facil, ¿no? Si trabajamos un poco con todo esto podemos conseguir automatizar los mensajes que se van a publicar en Facebook desde las páginas que gestionamos.

Escribiendo en muros desde nuestra aplicación de Facebook

Domingo, 22 de Enero de 2012 Gaspar Fernández 9 comentarios

fb_website3 Uno de los usos más extendidos de las aplicaciones de Facebook es el de escribir en el propio muro o en el muro de nuestros amigos. Vamos a hacer un ejemplo de esto utilizando la Graph API de Facebook, a través de la biblioteca oficial que ellos nos dejan en GitHub. Para empezar a crear la aplicación os recomiendo leer este post anterior donde se dice paso a paso cómo se debe crear y cómo empezar a escribir código.

Pedir permiso para publicar

Antes de nada, debemos pedir permiso para publicar en el muro del usuario, para pedir permiso, lo podemos hacer en el mismo momento que ejecutamos el método getLoginUrl() pasando como parámetro un array cuyo único elemento será ’scope’ y su valor serán los permisos requeridos separados por comas. Por ejemplo:

1
$facebook->getLoginUrl(array('scope' => 'publish_stream'));

El permiso que debemos pedir para poder publicar en los muros de Facebook es stream_publish. Por otra parte, puede que ya hayamos identificado la aplicación con anterioridad, por lo que al estar dentro del sistema no hacemos llamada a getLoginUrl(), para ello debemos comprobar los permisos de que disponemos y eso lo hacemos con una llamada a la API a /usuario/permissions:

1
print_r($facebook->api('/me/permissions'));

Lo que nos devolverá un array con los permisos que dispone la aplicación, el array tendrá un elemento ['data'] que será otro array, cuyo elemento [0] contendrá otro array con los permisos:

Array ( [data] => Array ( [0] => Array ( [installed] => 1, [publish_stream] =>1 ) ) )

fb_website2

Publicar un mensaje en mi muro

Para publicar un mensaje en mi muro, debemos hacer una llamada a /usuario/feed y enviar por post la información referente al mensaje deseado:

1
$facebook->api('/me/feed', 'post', array('message' => $mensaje));

Código fuente demo

En este código fuente, he integrado excepciones para controlar los posibles errores (No identificado, No tengo permisos, Facebook me ha devuelto un array incorrecto), en este caso, los errores de identificación son salvables, pero los demás no. Para probar este código, debes cambiar la $api_key y la $api_sec:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

$api_key = 'xxxxxxxxxxxxx';
$api_sec = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

require_once('facebook.php');

// Definimos códigos de error
define(NOT_INSTALLED,      1);
define(NO_PUBLISH_STREAM,  2);
define(MALFORMED_ARRAY,   90);

$facebook = new Facebook(array(  
                   'appId'  => $api_key,
                   'secret' => $api_sec,
                   'cookie' => true ,
                 ));

try
{
 
  $sesion = $facebook->getUser();
  if (!$sesion)
    throw new Exception('Aplicación no instalada', NOT_INSTALLED);

  echo "Estamos identificados en Facebook<br/>";
  echo "Usuario: ".$sesion."<br/>";

  // Obtenemos los permisos del usuario
  $permissions = $facebook->api('/'.$sesion.'/permissions');
  if (!isset($permissions['data'][0]))
    throw new Exception('Facebook ha devuelto un array mal formado', MALFORMED_ARRAY);

  if (!isset($permissions['data'][0]['publish_stream']))
    throw new Exception('No tengo permiso publish_stream', NO_PUBLISH_STREAM);

  $mensaje='Probando la publicación de mensajes en Facebook...';
  print_r( $facebook->api('/189639191053576/feed', 'post', array('message' => $mensaje)));

} catch (Exception $e)
{
  switch ($e->getCode())
    {
    case NOT_INSTALLED:
      $login_url = $facebook->getLoginUrl();
      header('Location: '.$login_url);
      die();
      break;
    case NO_PUBLISH_STREAM:
      $login_url = $facebook->getLoginUrl(array('scope'=>'publish_stream'));
      header('Location: '.$login_url);
      die();
      break;

    case MALFORMED_ARRAY:
      echo $e->getMessage();
      break;

    default:
      echo "Ocurrió un error no identificado";
    }
}
?>

Publicando en otros muros y páginas

Para publicar en el muro de otros usuarios, simplemente tenemos que sustituir la dirección de la llamada a la API donde publicamos de /me/feed a /usuario/feed donde usuario es el texto que aparece al acceder en la dirección de la página principal de Facebook de alguno de nuestros amigos (también puede ser su ID de usuario, pero ya es difícil de obtener).

Para publicar en páginas debemos sustituir el /usuario/feed por /id_de_pagina/feed donde el ID de la página es el número que aparece en la dirección de la página en cuestión, si por ejemplo, la URL de la página de Facebook de este blog es:https://www.facebook.com/pages/Poesía-Binaria/189639191053576 ; la id de la página es la que está en negrita.

Sólo teniendo el permiso publish_stream ya podemos publicar con el nombre de usuario que tenemos actualmente en cualquier lado dentro de Facebook.

Creando una aplicación para Facebook (paso a paso)

Miércoles, 18 de Enero de 2012 Gaspar Fernández 2 comentarios

monitor_poesia

He decidido hacer esta guía porque Facebook anda cambiando los métodos para hacer aplicaciones y varias partes de su API. Los chicos de Facebook no paran de meter y sacar cosas y no dejan la página quieta. Después de hacer varias guías para “publicar definitivamente” en Facebook, van y cambian la forma de hacerlo.

Aunque parece que se han estabilizado, todos estos cambios han sido para llegar a la Graph API, se ha quedado bien hecha y estable, y yo creo que es posible aprender mucho de ella.

Aunque en esta guía empezaré desde el principio, desde que se crea la aplicación, paso a paso, ya que actualmente crear una aplicación vale para muchas cosas, no sólo para algo que resida dentro de Facebook sino para webs o clientes que funcionan fuera de Facebook e interactúan con la red social.

He de decir también que esta guía está hecha en Enero de 2012, por lo que si entras aquí en el futuro, puede que hayan hecho otro cambios definitivo más en Facebook.

Primer paso: Crear la App

Para ello debemos dirigirnos a https://developers.facebook.com/apps. Éste será nuestro centro de control de aplicaciones, donde podremos ver y editar los datos de éstas. Allí encontraremos en la parte superior de la página:

facebook_create_app

Pulsamos sobre Create New App, tras ello veremos un diálogo como este:

facebook_create_app_dialogEn el que en:

  • App Display Name debemos decir el nombre de nuestra aplicación, o si es una aplicación para identificarnos en una página, el nombre de la página. Es un nombre que la identifique.
  • App Namespace es el nombre que tiene nuestra aplicación en la URL de aplicaciones de Facebook. Es decir https://apps.facebook.com/AppNamespace . Dependiendo del ámbito de nuestra aplicación (si es accesible a través de Facebook.com o no) rellenaremos este campo o no.

Si continuamos, a veces la web de Facebook dará un error (comprobado el 7 de Enero de 2012), por lo que podemos volver a la página de las aplicaciones y continuar.

En la configuración de la aplicación, le damos a Edit Settings, y saldrá una pantalla así:

facebook_app_basica

Aquí podremos rellenar el Namespace (mencionado antes), el mail de contacto y el dominio donde está alojada la aplicación (muy importante, ya que si la aplicación no está en el dominio indicado, no funcionará; además de la categoría de nuestra aplicación.

Por otra parte, arriba vemos la App ID y la App Secret. La primera es el identificador de nuestra aplicación, y la segunda una clave secreta que no se debe compartir con nadie para que la aplicación pueda interactuar con Facebook, algo así como el nombre de usuario y contraseña de nuestra aplicación. (Yo lo he puesto aquí, pero en realidad lo he regenerado varias veces).

La aplicación que crearemos servirá para enlazar una página web con Facebook y poder utilizar esa información, para eso debemos rellenar el apartado App Domain (por ejemplo minutodecaos.com), con el dominio donde estén alojadas las páginas de la aplicación, si no, la aplicación no estará autorizada y, un poco más abajo Site URL con la dirección exacta donde estará alojada nuestra aplicación.

fb_website

Código fuente de la App

Es hora de crear nuestra aplicación en PHP. Lo primero que tenemos que hacer es descargarnos los archivos de la API desde esta dirección, dentro de GitHub. En principio trabajaremos en la web en modo local, por lo que creamos un directorio en nuestro disco duro (proyectos/facebook/tests/ dentro de mi home) Y descomprimimos los archivos dentro del directorio de nuestro proyecto. Aunque no es estrictamente necesario, yo lo he descomprimido dentro de lib/facebook, por lo que esos archivos estarán en $HOME/proyectos/facebook/tests/lib/facebook; y creamos el siguiente index.php (que luego subiremos al servidor junto con los ficheros de biblioteca de Facebook) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

$api_key = 'xxxxxxxxxx';
$api_sec = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

require_once('lib/facebook/facebook.php');

$facebook = new Facebook(array(  
                   'appId'  => $api_key,
                   'secret' => $api_sec,
                   'cookie' => true ,
                 ));

$sesion = $facebook->getUser();
if ($sesion)
  {
    echo "Estamos identificados en Facebook<br/>";
  }
 else
  {
    echo "No estamos identificados en Facebook ";
    $login_url = $facebook->getLoginUrl();
    echo '<a href="'.$login_url.'">Click para identificarte</a>';
  }

?>

Este código nos mostrará, la primera vez que entremos: “No estamos identificados en Facebook. Click aquí para identificarte”, eso no significa que no hayamos entrado a la página de Facebook, significa que la página web no te ha identificado como usuario y de ser autorizada, por eso hacemos click en la pantalla anterior y aparecerá lo siguiente:
fb_website1

Login automático

Si no queremos mostrar el enlace para identificarnos en la aplicación, podemos utilizar el siguiente código:

1
2
3
4
5
6
7
8
if ($sesion)
   echo "Estamos identificados en Facebook";
else
{
   $login_url = $facebook->getLoginUrl();
   header('Location: '.$login_url);
   die();
}

Mostrando datos de usuario, o cogiéndolos

En la parte de “Estamos identificados en Facebook”, podemos hacer:

1
2
3
4
5
6
7
if ($sesion)
{
   echo "Estamos identificados en Facebook<br/>";
   echo "Usuario: ".$sesion."<br/>";
   $userData = $facebook->api('/me');
   echo nl2br(print_r($userData, true));
}

Con estas líneas podemos ver información del usuario que está actualmente identificado en nuestra aplicación, y podremos utilizar los datos del array $userData:

  • ['name'] - Nombre completo del usuario
  • ['first_name'] - Nombre
  • ['last_name'] - Apellidos
  • ['link'] - Enlace a la página del usuario en Facebook
  • ['username'] - Nombre de usuario de Facebook
  • ['about'] - Frase personal
  • ['gender'] - Género
  • y mucho más que podemos ver cuando ejecutamos el ejemplo anterior

Ahora en Facebook, siempre que queramos acceder a información tanto de páginas, grupos, usuarios, etc, sólo tenemos que acceder a través de la llamada a api(’/localizacion’), con la palabra especial /me, como hemos visto para el usuario actual. Esto nos puede ayudar a identificarnos en nuestra web, sin pedir usuario, ni contraseña, a través de la Graph Api.

C.I. X: Creando un Framework PHP, Microsoft y Nokia a lo suyo, mejores momentos para publicar, clones libres de juegos

Domingo, 3 de Julio de 2011 Gaspar Fernández Sin comentarios

Una pequeña recopilación de enlaces de estos días:

Facebook VS Google Adsense

Viernes, 20 de Mayo de 2011 Gaspar Fernández 7 comentarios

Estuvieron amenazando y por fin el día ha llegado. Hace unos meses, el equipo de Facebook enviaba varios mails a los usuarios avisando del cambio en sus condiciones de servicio y que iban a permitir como nuestro proveedor de publicidad alguno de una lista de empresas.

La lista está muy bien, y hay bastantes, sólo habrá que verlos uno a uno y estudiar su funcionamiento. El tema es que somos muchos los desarrolladores de aplicaciones que trabajamos con Google Adsense, y aunque el principio todos teníamos miedo de que Google no aceptara ser incluido en aplicaciones de Facebook, al final ha sido Facebook el que no ha permitido que incluyamos publicidad de Google.

Las medidas que ha tomado Facebook han sido drásticas: todas las aplicaciones que tuvieran publicidad de Google han sido suspendidas por una violación del contrato, aunque el mismo día que envían el aviso a los desarrolladores, tendremos otra oportunidad de rescatar la web antes de pasar a tener un bloqueo mayor (nos dan una oportunidad al menos).

Lo veo una medida demasiado fuerte, ya que tienen la costumbre de parsear los html de las aplicaciones, aunque planea prohibirlo pronto, y tendremos que ir adaptando las aplicaciones.

Por último, decir que Facebook se está fijando en las aplicaciones que tienen un determinado número de visitas mensuales y según mi experiencia, ese número está fijado en menos de 6000.

Por lo tanto, si tienes una aplicación para Facebook, con publicidad de Google Adsense, ándate con ojo, y busca alternativas antes de que sea demasiado tarde.

Nueva página en Facebook

Sábado, 8 de Enero de 2011 Gaspar Fernández Sin comentarios

poesia_binaria

Desde ayer, he puesto una página en Facebook para los seguidores del blog. Si te parece interesante, haz click en Me Gusta.

Categories: facebook Tags: , , ,

Login a Facebook y acceso a aplicación automatizado

Miércoles, 11 de Agosto de 2010 Gaspar Fernández Sin comentarios

A medida que va creciendo Facebook, los desarrolladores van siendo más imaginativos a la hora de crear aplicaciones que trabajen sobre esta red. Actualmente existen clientes para Facebook que no necesitan que estemos dentro de la página, y lo que presento a continuación es un pequeño ejemplo de todo ello.

Este script es parte investigación / parte navegación y lectura de foros en los que no he encontrado la respuesta exacta a mis necesidades. El problema está en que, a pesar de la existencia de Facebook Connect, si queremos automatizar tareas en Facebook tenemos que estar identificados en el sistema y entonces es cuando podemos hacer la tarea en cuestión.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

$face_cookie='/tmp/fcbk_cookie';
$useragent="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3";
$login_email='*************';
$login_pass='**************';

function curl_load_url($url, &$error, $postfields=false)
{
  global $useragent, $face_cookie;
  $cu = curl_init();
  curl_setopt($cu, CURLOPT_URL, $url);
  curl_setopt($cu, CURLOPT_HEADER, 0);
  curl_setopt($cu, CURLOPT_FOLLOWLOCATION, 1);
  curl_setopt($cu, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($cu, CURLOPT_USERAGENT, $useragent);
  curl_setopt($cu, CURLOPT_COOKIEJAR, $face_cookie);
  curl_setopt($cu, CURLOPT_COOKIEFILE, $face_cookie);
  if ($postfields)
    {
      curl_setopt($cu, CURLOPT_POSTFIELDS, $postfields);
      curl_setopt($cu, CURLOPT_POST, 1);
    }

  $cont=curl_exec($cu);
  $error=curl_errno($cu);

  curl_close($cu);

  return $cont;
}

function fb_login($email, $passwd)
{
  $error=false;
  curl_load_url('http://login.facebook.com/login.php', $error);

  $ch_test='&euro;,&acute;,€,´,水,Д,Є';
  $postfields='cuarset_test='.urlencode($ch_test).'&locale=es_ES&email='.urlencode($email).'&pass='.urlencode($passwd).'&pass_placeholder=&cuarset_test='.urlencode($ch_test);
  $cont=curl_load_url('https://login.facebook.com/login.php?login_attempt=1', $error, $postfields);

 /* Si hay un error de cURL lo decimos */
 if ($error)
   echo 'Error (cURL): '.$error."\n";

 /* Esta palabra *login_attempt* aparece en los intentos de login de Facebook */
 /* es raro que en la página principal salga. */
 /* Podemos también, verificar si está el enlace a editaccount.php para decir */
 /* que hemos sido identificados correctamente */
 if (strpos($cont, 'login_attempt')!==false)
/*  if (strpos($cont, 'editaccount.php')===false) */
   {
     echo 'Error (Facebook): E-mail o contraseña incorrecto';
     $err=1;
   }
 /* Si no hay errores nos daremos por identificados, aunque si el password es incorrecto */
 return (!$err);
}

if (fb_login($login_email,$login_pass)){
  $error=false;
  $cont = curl_load_url('http://apps.facebook.com/minutofilosofico/', $error);
  // Mostramos el contenido de la página
  echo $cont;
}
?>

¿Qué aplicaciones prácticas puede tener esto? Podemos hacer fácilmente un programa de escritorio para manejar Facebook, enviarnos por e-mail o un sms automáticamente si alguien que esperamos nos escribe, subir fotos de forma más rápida con un script en nuestro ordenador… o publicar un mensaje a la hora que hayamos especificado.

Como el ejemplo está en cURL será fácil portarlo a otro lenguaje con el que os sintáis más cómodos.

Sobre los 100 millones de usuarios de Facebook ¿Robados? ¿Filtrados?

Domingo, 1 de Agosto de 2010 Gaspar Fernández Sin comentarios

Hace unos días, surgió la noticia de un hacker, Ron Bowes de Skull Security, quien con un par de scripts (ahora mismo la web no funciona) ha conseguido recopilar toda la información pública de más de 100 millones de perfiles de Facebook, es decir, lo que es visible para todos, los que no tenemos como amigos, además es un archivo 100% legal, ya que lo único que la información recopilada es la que los usuarios comparten con todos. Por si fuera poco está publicada en un torrent 100% accesible a cualquiera.

Paso a continuación una serie de enlaces donde ver la noticia: Alt1040, Blog de Manuel Pereira González, ABC, Thinq, y muchos más sitios.

Aunque en muchos titulares habla de que el archivo incluye números de teléfono y fechas de nacimiento, querría desmentir todo aquello, copio un fragmento del archivo README con el contenido del archivo:

facebook.rb The script used to generate these files (v1)
facebook.nse The script that will be used for the second pass (v2)
facebook-urls The full URLs to every profile
facebook-names-original All names, including duplicates
facebook-names-unique All names, no duplicates
facebook-names-withcount All names, no duplicates but with a count
facebook-firstnames-withcount All first names (with count)
facebook-lastnames-withcount All last names (with count)
facebook-f.last-withcount All first initial last name (with count)
facebook-first.l-withcount All first name last initial (with count)

Vemos que, como mucho, contiene el nombre y la URL, aunque por otra parte, he de decir que no sería demasiado difícil extraer los datos que figuren como públicos en estos perfiles, aunque todavía hay esperanza para aquellos que no han hecho sus datos privados.

Aunque por otra parte, yo que tengo el perfil abierto, con todos los datos públicos, no aparezco en el listado, por lo que es interesante buscarse. Para ello:

$ bzcat facebook-urls.txt.bz2 | grep [identificativo de tu URL de Facebook]

Donde el [identificativo de tu URL de Facebook] es lo que ponemos en la barra de direcciones para acceder a nuestro perfil: http://www.facebook.com/….

O también podemos buscar por nombre

$ bzcat facebook-names-unique.txt.bz2 | grep nombre

Así saldrán todos los que se llaman como tú.

Eso sí, leo en Alt1040 otra noticia, muchas empresas se están descargando el torrent, a pesar de sus políticas de protección de datos, anti-torrents, etc, y esperemos que en los próximos días no empiece a llegar spam por Facebook.

Cuando Facebook hace de las suyas [ BUG CSS ]

Sábado, 17 de Abril de 2010 Gaspar Fernández Sin comentarios

Durante este año y varias veces ha habido un pequeño bug CSS que hace que los que mantenemos aplicaciones para Facebook (y no es un trabajo a tiempo completo) nos tiremos de los pelos.

Y es que al cargar nuestra aplicación, los estilos css no funcionan, no cargan, y si cargamos el archivo de Facebook del tipo:

http://external.ak.fbcdn.net/fbml_static_get.php?src=http%3A%2F%2Fmiurl.com%2Faplicacion%2Fcss%2Ffilo.css%3F_fb_q%3D1&appid=107083291268&pv=1&sig=5ee8229e4afbee29836224de876dfa&filetype=css

nos devolverá un precioso mensaje que dice:

Parámetro no válido: Error desconocido

Lo mejor es que el mensaje está traducido al español, por lo que al principio podemos sospechar que falla nuestra aplicación y luego cuando buscamos el error lo tenemos más difícil, aunque podemos buscar lo siguiente (aparece también en inglés, según nuestra localizacion):

Invalid parameter: Unknown error

El bug aún está abierto (a día 17 de Abril de 2010): podéis consultar el estado actualizado aquí.

Pero mientras investigaba el bug, encontré un pequeño fragmento de código interesante (y podemos utilizarlo como solución temporal al problema):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function minify( $css ) {
        $css = preg_replace( '#\s+#', ' ', $css );
        $css = preg_replace( '#/\*.*?\*/#s', '', $css );
        $css = str_replace( '; ', ';', $css );
        $css = str_replace( ': ', ':', $css );
        $css = str_replace( ' {', '{', $css );
        $css = str_replace( '{ ', '{', $css );
        $css = str_replace( ', ', ',', $css );
        $css = str_replace( '} ', '}', $css );
        $css = str_replace( ';}', '}', $css );

        return trim( $css );
}

function includeStyleCSS($filename)
{
        // due to: http://bugs.developers.facebook.com/show_bug.cgi?id=9053
        // We either must print the stylesheet inline
        // or include it with a link tag that does not include rel="stylesheet".
        // Fixed 3/6/2010
        // Broken 4/13/2010:http://bugs.developers.facebook.com/show_bug.cgi?id=9601

        // use this block when linked CSS is broken
        echo "<style type=\"text/css\">";
        $content = @file_get_contents($filename);
        echo minify( $content );
        echo "</style>";

        // use this block when linked CSS is working
        //      echo "<link rel=\"stylesheet\" href=\"http://MYSERVER.COM/$filename\" type=\"text/css\" />\n";
}

He dejado el fragmento de código original, pero podemos verlo atentamente y analizar lo que hace:

  • Dentro de minify(), el primer regexp_replace elimina cuando hay más de un espacio seguido; el segundo, elimina los comentarios. Los str_replace que le siguen, sirven para eliminar espacios sobrantes cerca de caracteres de inicio y fin, y separación.
  • includeStyleCss() introduce dentro de nuestro archivo resultante el CSS del archivo (más o menos reducido por minify()).

Hay que destacar que es una medida provisional, pero es interesante incluir este código en nuestras aplicaciones porque Facebook es reincidente en este fallo y no descartamos que vuelva a ocurrir.

Pero bueno, como yo no me puedo quedar quieto, vamos a intentar mejorar este código (propuesto en la discusión del bug por Ed Holzwarth, aunque he podido encontrar algún fragmento de minify por la red.

La modificación de este código viene de un poquito de investigación por otras webs:

1
2
3
4
5
6
7
8
9
10
11
12
13
function minify($css)
{
  // Quitamos comentarios
  $css = preg_replace('#/\*.*?\*/#s', '', $css);
  // Quitamos espacios en blanco cerca de {}|:;,
  $css = preg_replace('/\s*([{}|:;,])\s+/', '$1', $css);
  // Quitamos espacio en blanco al inicio
  $css = preg_replace('/\s\s+(.*)/', '$1', $css);
  // Quitamos ; innecesarios
  $css = str_replace(';}', '}', $css);

  return $css;
}

Por cierto, sería interesante aplicar este minificador al script de cache y compresión de ficheros CSS. que publiqué hace un tiempo.

Visita otras webs de la red