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.
Tabla de contenidos
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.
Pingback: Bitacoras.com /
Pingback: BlogESfera.com /
I learned a lot from your blog, and you can learn more about older video games to have more engaging experiences. I look forward to playing with you in the past!