Archivo

Archivo para la categoría ‘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.

Publicando mensajes en Facebook sin que el usuario esté ahora mismo en la web [ modo offline ]

Viernes, 27 de Enero de 2012 Gaspar Fernández 6 comentarios

enchufe

Una de las grandes utilidades que nos da Facebook por si creamos una aplicación de escritorio, o una aplicación web que publique posts de nuestro blog automáticamente en nuestro muro, son los mensajes Offline, con este modo, no es necesario que un usuario esté identificado realmente en Facebook, aunque, debemos tener cuidado a la hora de trabajar con la aplicación, los usuarios nos han dado permiso para publicar en su nombre contenidos que nosotros generamos, por lo que debemos evitar que se pueda acceder a la publicación de contenidos directamente. Es decir, lo que voy a mostrar ahora es un mero ejemplo de cómo se haría, aunque muestro un programa que es lo más inseguro del mundo, ya que, cualquiera que entre en la dirección web especificada podrá escribir en Facebook con nuestro ID de usuario.

Creando la aplicación y practicando la publicación

Para esto, hay dos posts anteriores que te recomiendo leer si no lo has hecho ya:

Creando dos interfaces

Por un lado necesitamos la interfaz que conecta con Facebook, tal y como la hemos hecho ya en el post anterior, desde aquí se pedirá permiso para poder publicar mensajes, y para poder acceder de forma offline. Este será nuestro index.php en los ejemplos (aunque podemos cambiarlo por cualquier página que destinemos a la identificación en Facebook).

Por otro lado, necesitamos el script que realmente va a publicar texto en Facebook, este script no debe identificarse en el sistema, sólo debe enviar la publicación (será en el ejemplo publica.php)

El código fuente completo podrás verlo y descargarlo al final del post.

Pidiendo permiso

Para escribir en Facebook con el modo offline, debemos pedir el permiso, concretamente el permiso offline_access. Con este permiso la palabra clave que nos da acceso con el usuario elegido no caducará (las claves normales, sin offline access, tienen una caducidad limitada, aunque funcionarán durante un tiempo (¿minutos?) aunque el usuario haya dejado de estar activo).

Para manejar los permisos de Facebook de una mejor forma, he extendido la clase Facebook con algunos métodos que nos ayudarán a la hora de pedir permisos:

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
<?php
  /**
   *************************************************************
   * @file facebook_ext.php
   * @brief Extensión de la clase Facebook que permite manejar
   *        algunas opciones de forma más intuitiva.
   *
   * @author Gaspar Fernández <blakeyed@totaki.com>
   * @version
   * @date 14 ene 2012
   * Historial de cambios:
   *
   *
   *
   *************************************************************/


require ('facebook.php');

class FacebookExtended extends Facebook
{
  private $permissions=false;

  function __construct($config)
  {
    parent::__construct($config);
  }

  function askForPermission($ext_perm, $uid=false)
  {
    if (!$uid)
      $uid=$this->getUser();

    if (!$this->permissions)
      $this->permissions=$this->api('/'.$uid.'/permissions');
   
    if ( (isset($this->permissions['data'])) && (isset($this->permissions['data'][0])) )
      return $this->permissions['data'][0][$ext_perm];
  }

  function askForPermissions($ext_perms, $uid=false)
  {
    $permArray = explode(",", $ext_perms);

    $permissionsOk=true;

    $nElems=count($permArray);
    for ($i=0; $i< $nElems; $i++)
      {
    $ext_perm=trim($permArray[$i]);
    if ($ext_perm!='')
      {
        /* Internal debug */
        /* echo $i.'-'.$this->askForPermission($ext_perm, $uid)."<br>"; */
        $permissionsOk= ($this->askForPermission($ext_perm, $uid) && $permissionsOk);
      }
      }
    return $permissionsOk;
  }

  function loginUser($permissions)
  {
    if ($permissions)
      $loginUrl=$this->getLoginUrl(array('scope'=>$permissions));
    else
      $loginUrl=$this->getLoginUrl();

    header('Location: '.$loginUrl);
    exit;
  }

};
?>

Esta clase, se encargará de preguntar por los permisos que necesitamos de forma automática (en realidad fue como se explicó en el post anterior, aunque cuando tenemos que preguntar por varios permisos nuestro código puede crecer bastante).

Ahora, para pedir permiso haremos lo sigueinte:

1
2
3
4
$permissions = $facebook->askForPermissions('publish_stream,offline_access');
   
  if (!$permissions)
    throw new Exception('No tengo permisos suficientes', NO_PERMISSIONS);

La excepción podemos crearla como queramos, yo he seguido la técnica del post anterior, que podréis observar mejor con el código completo, lo que está claro es que el código no debe continuar pasado este punto, y debemos pedir los permisos necesarios. Además, a la hora de pedir los permisos, con la clase que hemos visto anteriormente, podemos hacer lo siguiente:

1
$facebook->loginUser('publish_stream,offline_access');

Con lo que también nos ahorramos unas líneas de código.

También, para publicar en nombre de los usuarios debemos obtener un Access Token, es una palabra de acceso única que identifica al usuario de Facebook en nuestra aplicación y nos permite interactuar, para ver esta palabra debemos hacer:

1
echo $facebook->getAccessToken();

Publicando contenido

Para publicar contenido, ahora hemos creado el archivo publica.php que sólo publicará contenido en el muro, con este archivo tenemos que tener especial cuidado, ya que en este caso, cualquiera podrá publicar contenido nada más accediendo al archivo (Código fuente de 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
<?php

$api_key = 'Rellenar con nuestra API key';
$api_sec = 'Rellenar con nuestra API secret';

require_once('facebook_ext.php');

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

try
{
  $destino="gaspy";     // O el nombre de usuario que queramos usar
  $public='Probando mensajes automáticos con el modo offline';
  $access_token='palabra que vimos cuando nos autorizamos, muy laarga';

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

Ahora, para publicar contenido, en la llamada a la API debemos especificar:

  • uid = UID con la que queremos publicar, es decir, el usuario en nombre de quién hablamos.
  • message = Mensaje que queremos publicar
  • access_token = Palabra de acceso

Es más, podemos publicar en el muro o la página de quien queramos con esta técnica, igual que hacíamos antes, pero en este caso, lo hacemos sin que tengamos que estar identificados como ese usuario.

Código fuente de index.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
<?php

$api_key = 'Rellenar con nuestra API key';
$api_sec = 'Rellenar con nuestra API secret';

require_once('facebook_ext.php');

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

$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('publish_stream,offline_access');
   
  if (!$permissions)
    throw new Exception('No tengo permisos suficientes', NO_PERMISSIONS);
 
  echo "No tienes que hacer nada, cierra esta ventana.";
}
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('publish_stream,offline_access');
      break;

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

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

Para descargar el código fuente: modooffline.tar.bz2 (1.7Kb)
Hay que incluir la API de Facebook para que funcione y sustituir $api_key y $api_sec por nuestra API Key y API secret respectivamente.

Foto: Samuel M. Livingston (Flickr)

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:

Recopilación de soluciones para los retos de #tuentiContest . Challenge #2

Miércoles, 22 de Junio de 2011 Gaspar Fernández 2 comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que haerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #2 : TLang

Se trata de implementar un parser que suma, reste y multiplique, con los símbolos ^= ,^# 2 2 y ^@, eso sí, el final de la operación siempre lo marcará un $. Por otra parte, hay símbolos, como ^@ (resta) que pueden ir sólo con un número, en lugar de con varios. Debemos leer de la entrada las operaciones a realizar y devolver el número de salida.

Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización: 2011/06/22 13:54 : Error tipográfico
Actualización: 2011/06/22 20:00 : Añadida solución de @Puigcerber
Actualización: 2011/06/28 07:58 : Añadida solución de @theom3ga
Actualización: 2011/07/02 22:30 : Añadida solución de @frisco82
Actualización: 2011/07/03 13:30 : Añadida solución de @Rosapolis
Actualización: 2011/07/08 12:37 : Añadida solución de captain_regex

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.

Visita otras webs de la red