<?php
## la-cita-del-dia.php
## postea en twitter la cita del día que aparece en el diario el mundo (http://www.elmundo.es/diario)
## así como el titular de la noticia a que hace referencia
## y una URL a noticias semejantes en news.google.es

## this script copies a sentence plus a related headline from Spanish
## newspaper El Mundo (http://www.elmundo.es/diario)
## and then posts it into Twitter (http://twitter.com/lacitadeldia)
## along with a tiny-url for related news at news.google.es


// prevent execution. PLEASE REMOVE.
// evita que el ejemplo se ejecute. BORRAR!
EXIT;



// CONSTANTS:
// user for twitter:
// usuario para twitter:
$twitter_user   "USUARIO"// twitter.com/USUARIO
// password for twitter:
// contraseña del usuario:
$twitter_pw     "PASS";


// benchmarking
// tomado de http://es2.php.net/microtime
function microtime_float()
{
    list(
$useg$seg) = explode(" "microtime());
    return ((float)
$useg + (float)$seg);
}

// marcar inicio de ejecución
// time = 0
$time microtime_float();

// FAILOVER - a prueba de fallos
// Twitter is usually down for maintenance for short periods. If you plan to let this script as a cron task
// you should use this part in order to have the script doing the posting later if twitter is down,
// and plan your crontab acordingly.
// You can set this script to work for cron setting this task (ask your hosting provider):
//
//  /usr/bin/php /full/path/to/your/script/la-cita-del-dia.php
//
// Also, check your ISP for paths relating to your hosting.
//
// Don't forget your hosting can be at another timezone!
//
// We use a MySQL db. You can easily change this to Postgres if you want.
// Use "result" field to store verbose results if you want to debug
// For the bad news there are two posts, and if the first goes well and the second don't,
// it's assumed the result is OK. Also, if the posting fails for the whole day,
// it's lost. Just didn't want to bother this Sunday.
// You can also invoke this script from your browser and have it work manually.
// set failover to true
// and write your db details here
// you should create this table also, and fill the only register:

    /*
            -- 
            -- Table structure for table `twitter_poster_control`
            -- 
            
            CREATE TABLE `twitter_poster_control` (
              `id` tinyint(4) NOT NULL default '0',
              `date` date NOT NULL default '0000-00-00',
              `status` tinyint(1) NOT NULL default '0',
              `result` text character set latin1 collate latin1_spanish_ci NOT NULL,
              PRIMARY KEY  (`id`)
            ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
            
            -- 
            -- Dumping data for table `twitter_poster_control`
            -- 
            
            INSERT INTO `twitter_poster_control` (`id`, `date`, `status`, `result`) VALUES (1, '2007-05-21', 0, '');
    */

// A PRUEBA DE FALLOS
// Twitter está parado a menudo y posteo no funciona. Para que el script vaya como una tarea programada
// deberías activar este apartado que verifica si el posteo ha ido bien en el día,
// y programar Cron en consecuencia.
// Para invocar el script desde Cron, usa este comando (consulta a tu proveedor si no estás seguro)
//
//  /usr/bin/php /ruta/absoluta/a/tu/script/la-cita-del-dia.php
//
// ¡y recuerda ajustar las zonas horarias!
//
// Usamos MySQL, pero puedes migrar esto a PostgreSQL con facilidad.
// Puedes utilizar el campo "result" para almacenar más detalles si quieres depurar.
// El sistema no es perfecto: hay dos posteos. Si el primero va bien y el segundo no
// asumimos que el resultado es Ok. Si el posteo del día no termina de salir, se pierde,
// porque tampoco está programado para hacerlo retroactivo.
// Puedes invocar este script manualmente desde tu navegador.
// Usa esta tabla, y rellena el registro correspondiente

    /*
        -- 
        -- Table structure for table `twitter_poster_control`
        -- 
        
        CREATE TABLE `twitter_poster_control` (
          `id` tinyint(4) NOT NULL default '0',
          `date` date NOT NULL default '0000-00-00',
          `status` tinyint(1) NOT NULL default '0',
          `result` text character set latin1 collate latin1_spanish_ci NOT NULL,
          PRIMARY KEY  (`id`)
        ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
        
        -- 
        -- Dumping data for table `twitter_poster_control`
        -- 
        
        INSERT INTO `twitter_poster_control` (`id`, `date`, `status`, `result`) VALUES (1, '2007-05-21', 0, '');
    */

// activate failover: true (set it to false if you don't want to use DB.
// activar failover: true (poner a false si no quieres usar este apartado)
$failover   true;
// db details:
$dbhost     "";
$dbname     "";
$dbuser     "";
$dbpass     "";

// open db connection
// conexión a la base de datos
if ($failover === true)
{
    
// try connect to dbserver
    
if (!$dbconn mysql_connect($dbhost$dbuser$dbpass))
    {
        
// error
        
echo "Error al conectar al servidor de base de datos. Error while connecting to dbserver!";   
        
// exit
        
exit;
    }
    else
    {
        
// connect to db
        
if (!mysql_select_db($dbname,$dbconn))
        {
            
// error
            
echo "Error al conectar a la base de datos. Error while connecting to database!";   
            
// exit
            
exit;           
        }
        else
        {
            
// check if the post is already done today
            // verificar si hoy se ha hecho el posteo
            
$q "SELECT date, status FROM twitter_poster_control WHERE id = 1";
            
// execute
            
$r mysql_query($q$dbconn);
            
// fetch
            
$fetch mysql_fetch_assoc($r);
            
            
// verify date and no command comming
            // verificar fecha (y que no lleguen comandos)
            
if ($fetch["date"]==date("Y-m-d") && $fetch["status"]!=&& !isset($_GET["accion"]))
            {
                
// silent exit...
                // salir silenciosamente.
                
exit;
            }
            
            
// verify status blocked and no command comming
            // verificar si el servicio está parado (y que no lleguen comandos)
            
if ($fetch["status"]==&& !isset($_GET["accion"]))
            {
                
// silent exit...
                // salir silenciosamente.
                
exit;
            }
        }
        
    }
}


// PARA POSTEAR EN TWITTER:
// TOMADO DE http://morethanseven.net/posts/posting-to-twitter-using-php/
// A simple function using Curl to post (GET) to Twitter
// Kosso : March 14 2007

// Feel free to do what you like with this.
// It's pretty easy. But I thought I'd just put it out there.
// Curl is your friend. 

// usage :  postToTwitter("myusername","mypassword","hello twitterati! I'm posting this from a PHP script! woo!");

/////////////////////////////////////////////////////////////////////


function postToTwitter($username,$password,$message){

    
// GET the API url via web authentication
    // add 'status' param to send a message to Twitter

    
$host "http://twitter.com/statuses/update.xml?status=".urlencode(stripslashes(urldecode($message)));

    
$ch curl_init();
    
curl_setopt($chCURLOPT_URL$host);
    
curl_setopt($chCURLOPT_VERBOSE1);
    
curl_setopt($chCURLOPT_RETURNTRANSFER1);
    
curl_setopt($chCURLOPT_USERPWD"$username:$password");
    
curl_setopt($chCURLOPT_HTTP_VERSIONCURL_HTTP_VERSION_1_1);
    
curl_setopt($chCURLOPT_POST1);

    
// Go for it!!!
    
$result curl_exec($ch);
    
// Look at the returned header
    
$resultArray curl_getinfo($ch);

    
// close curl
    
curl_close($ch);

    
//echo "http code: ".$resultArray['http_code']."<br />";

    
if($resultArray['http_code'] == "200"){
        
// message
        
echo "<br />OK! posted to http://twitter.com/".$username."/<br />";
        
// return ok
        
return true;
    } else {
        
// message
        
echo "eek! yegads! error posting to Twitter: error ".$resultArray['http_code'];
        
// return ko
        
return false;
    }

    
// function follows here if you want to debug...
    // sigue si quieres depurar o ver las respuestas de tw
    // debug the result
    // echo "<pre>";
    // print_r($resultArray);
    // echo "</pre><hr>";

    
$sResult htmlentities($result);
    
$sResult str_replace("&gt;&lt;","&gt;<br />&lt;",$sResult);

    
// 
    
echo "<pre>";
    print 
$sResult;
    echo 
"</pre>";

}

// SOME COMMANDS TO MANUALLY INVOQUE SCRIPT AND DO SOME MAINTENANCE if you have db support enabled.
// ALGUNOS COMANDOS PARA INVOCAR EL SCRIPT A MANO Y REALIZAR MANTENIMIENTO si usas base de datos.

// example: http://yourdomain.com/la-cita-del-dia.php?accion=showstatus

    // showstatus: muestra el registro de la base de datos y la ayuda
    // showstatus: show db register to take a look and shows help
    
    // reset0: deja el campo status a 0 para que el script pase de nuevo
    // reset0: sets the status to 0 in order to have the script execute again
    
    // reset1: deja el campo status a 0 para que el script pase de nuevo
    // reset1: sets the status to 0 in order to have the script execute again
    
    // block: marca el campo status a 2 para que el script no se ejecute
    // block: sets status field to 2 in order to stop the service
    
    // help: ayuda

// verify if any command is coming
// comprobar si llega algún comando
if (isset($_GET["accion"]))
{
    
// case...
    
switch ($_GET["accion"])
    {
        
// showsatus & help
        
case "showstatus":
        case 
"help":
            
// verify message
            // verificar si viene un mensaje
            
if (isset($_GET["message"]))
            {
                
// echo
                
echo "<pre>".$_GET["message"]."</pre>";
            }
            
            
// echo
            
echo "Mostrando contenido de la tabla. Showing table contents\n";
            
// sql: get data
            
$q "SELECT * FROM twitter_poster_control";
            
// execute
            
$r mysql_query($q$dbconn);
            
// fetch
            
while ($row mysql_fetch_assoc($r)) {
                echo 
"<pre>"print_r($row); echo "</pre>";
            }
      
            echo 
"\nAYUDA-HELP<pre>\n\n";
            echo 
"IMPORTANT: local server time is\n";
            echo 
"ATENCIÓN: la hora local del servidor es ".date("Y-m-d h:i:s")."\n\n";
            echo 
"Example: ".$_SERVER['SCRIPT_NAME']."?accion=showstatus\n\n";
            
            echo 
"showstatus: muestra el registro de la base de datos y esta ayuda\n";
            echo 
"showstatus: show db register to take a look. Also displays help\n\n";
            
            echo 
"reset0: deja el campo status a 0 para que el script pase de nuevo\n";
            echo 
"reset0: sets the status to 0 in order to have the script execute again\n\n";
            
            echo 
"reset1: deja el campo status a 1 para que el script no pase de nuevo hoy\n";
            echo 
"reset1: sets the status to 1 in order to avoid the script execute again today\n\n";
            
            echo 
"block: marca el campo status a 2 para que el script no se ejecute\n";
            echo 
"block: sets status field to 2 in order to stop the service\n\n";
            
            echo 
"help: ayuda\n";
            
            
// exit
            
exit;
            
        break;
        
        
// reset0
        
case "reset0":
            
// prepare SQL (executed later - se ejecuta después)
            
$q "UPDATE twitter_poster_control SET status = 0 WHERE id = 1";
        break;
        
        
// reset1
        
case "reset1":
            
// prepare SQL (executed later - se ejecuta después)
            
$q "UPDATE twitter_poster_control SET status = 1 WHERE id = 1";
        break;

        
// block
        
case "block":
            
// prepare SQL (executed later - se ejecuta después)
            
$q "UPDATE twitter_poster_control SET status = 2 WHERE id = 1";
        break;
    
        
// default
        
default:
            
// valores no controlados
            // exit if no allowed value
            
exit;
        
// just to keep tabbing
        
break;
    }
    
    
// execute querys
    // ejecutar la consulta
    
$r mysql_query($q$dbconn);
    
// check -verificar
    
if (mysql_affected_rows($dbconn)!=1)
    {
        
// error
        
echo "MySQL query error ".$q;
        
        
// exit
        
exit;
    }
    else
    {
        
// redirect to myself and showstatus
        // autoinvocarse mostrando status
        
header ("Location: ".$_SERVER['SCRIPT_NAME']."?accion=showstatus&message=".$q);
        
        
// echo
        
echo "OK. Redirigiendo en 4 segundos"
        echo 
"Query OK: ".$q;
        
        
// flush
        
flush();
        
// wait - esperar un poco ...
        
sleep(4);
        
        
// exit
        
exit;        
    }
}

/* frase diaria del mundo */
/* get aphorism and headline */

// abrir página de la edición impresa del mundo
// open remote page
if (!$r file("http://www.elmundo.es/diario/""r"))
{
    
// error
    
$error "No se puede abrir http://www.elmundo.es/diario/";

        
// failover test
        // comprobar si se usa failover
        
if ($failover===true)
        {
            
// sql: update status
            
$q "UPDATE twitter_poster_control SET status = 0, result = 'Fail to connect to el mundo.es', date = '".date("Y-m-d")."' WHERE id = 1";
            
// execute
            
$r mysql_query($q$dbconn);
            
// check -verificar
            
if (mysql_affected_rows($dbconn)!=1)
            {
                
// error
                
echo "MySQL query error ".$q;
                
                
// exit
                
exit;
            }
        }
        
// exit
        
exit;
        
}
else
{
    
/* obtener la frase */
    
        // all the file goes into $html
    // recomponer todo el fichero en una sola variable
    
$html implode (''$r);;
    
        
// free r
        // liberar $r
        
unset($r);
        
        
// explode $html to locate the aphorism.  Explode only into 2 parts 
    // trocear $r buscando la etiqueta de la cita, limitando elementos a 2...
    
$array_1 explode (" <td align=\"center\" class=\"frasediaria\">"$html 2);
    
        
// then, lets search the ending part
    // trocear el segundo elemento separando por </a>
    
$array_2 explode ("</td>"$array_1[1], 2);
    
        
// debug
    //print_r($array_2);
    
        // store aphorism
    // recomponer el elemento que nos interesa
    
$aphorism $array_2[0];
        
        
// locate headline in the same fashion as aphorism...
        // localizar el titular
        
$array_3 explode("<td colspan=\"2\" class=\"titulo2\">"$array_2[1], 2);
        
        
// ... using explode to break the file into pieces
    // quitar el resto de la página
        
$array_4 explode("</td>"$array_3[1], 2);
        
        
// store headline
        // obtener el titular
        
$headline trim($array_4[0]);
        
        
// extract URL. As the scope is now limited, we can use substr.
        // If you have php5, you can use strripos, but the idea is the same
        // extraer la URL (href...) Con php5, puedes usar strripos
        
$url_headline substr($headline, (strpos($headline"\"")+1), (strpos($headline"\" class")-strpos($headline"\"")-1));
        
        
// if you want to aim to the private ($) area use this URL. Else, we later aim to googlenews.
        // concatenar el principio de la url
        
$url_headline "http://www.elmundo.es/diario/".$url_headline;
        
// la página es de pago...
        // mejor vamos a google news (véase más abajo),
        // pero de todas formas lo dejamos hecho.
        
        // remove all tags from headline
        // dejar el titular sin html
        
$headline trim(strip_tags($headline));
        
        
// free memory
    // liberar memoria borrando las variables que no necesitamos.
    // página
    
unset($html);
    
    
// troceos
    
unset($array_1);
    unset(
$array_2);
    unset(
$array_3);
    unset(
$array_4);        
}

// build a query for googlenews. As Spanish language uses high unicode characters,
// you should urlencode the headline. 
// construir url para consultar en google news. Hay que convertir el titular a urlencode
$url_google_news "http://news.google.es/news?hl=es&ned=es&q=\"".urlencode($headline)."\"&btnG=Buscar+en+Noticias";

// ask for a tinyurl. You can replace googlenews and point to elmundo.
// solicitar URL a tinyurl
// si quisieras poner la URL de elmundo, cambia $url_google_news por $urltitular
if (!$r file("http://tinyurl.com/api-create.php?url=".$url_google_news"r"))
{
    
// error
    
$error "No se puede abrir tinyurl";
        
        
// let's have an empty tinyurl to gracefully fail...
        // si esto falla, lo dejamos pasar. Ya te darás cuenta de que no hay tiny url...
        
$tinyurl "";
}
else
{
        
// the whole file is the tinyurl    
    // recomponer todo el fichero en una sola variable
    
$tinyurl implode (''$r);;
        
        
// liberar $r
        
unset($r);     
}

// join headline and tinyurl to post both together
// juntar url y titular
$full_headline $headline." ".$tinyurl;

// let's see if the full headline is too long for twitter (140 chr)
// twitter truncates it if you want, but we don't want to post a bad url...
// verificar si la suma de URL y titular sobre pasa los 140 chr
if (strlen($full_headline)>140)
{
    
// so, we only send the headline (twitter can still truncate it)
    // sólo se enviará el titular (y que twitter lo trunque como crea conveniente
    
$headline_to_send $headline;
}
// else
// si no
{
    
// we send the full headline
    // se enviará el conjunto de titular y url:
    
$headline_to_send $full_headline;
}

// this is for debug:
echo "<pre>Frase capturada".utf8_encode($aphorism)."</pre>";
echo 
"<pre>Titular capturado".utf8_encode($headline)."</pre>";

// first, we post the headline
if (!postToTwitter($twitter_user$twitter_pwurlencode(utf8_encode($headline_to_send))))
{
        
// comprobar si se usa failover
        
if ($failover===true)
        {
            
// sql: update status
            
$q "UPDATE twitter_poster_control SET status = 0, result = 'Error al postear a twitter. Failed posting to twitter', date = '".date("Y-m-d")."' WHERE id = 1";
            
// execute
            
$r mysql_query($q$dbconn);
            
// check -verificar
            
if (mysql_affected_rows($dbconn)!=1)
            {
                
// error
                
echo "MySQL query error ".$q;
                
                
// exit
                
exit;
            }
        }
        
// exit
        
exit; 
}
// else-si no
{
    
// we hold the horses for a while: it seems there is something at twitter to avoid flooding.
    // retener para que no parezca un ataque
    
    // but first, a small echo to say we are alive and then flush to have the message being output
    // dar señales de vida y mandar el texto al navegador
    
echo "\n......\n";
    
flush();
    
sleep(10);
    echo 
"Continuando";
    
flush();
    
    
// then we post the aphorism
    
if (!postToTwitter($twitter_user$twitter_pwurlencode(utf8_encode($aphorism))))   
    {
            
// comprobar si se usa failover
            
if ($failover===true)
            {
                
// sql: update status: we mark the second posting as failed, but terminate OK
                // se marca el segundo resultado como KO, pero el resultado final es OK
                
$q "UPDATE twitter_poster_control SET status = 1, result = 'Error al postear a twitter el segundo post. Failed posting 2nd post to twitter', date = '".date("Y-m-d")."' WHERE id = 1";
                
// execute
                
$r mysql_query($q$dbconn);
                
// check -verificar
                
if (mysql_affected_rows($dbconn)!=1)
                {
                    
// error
                    
echo "MySQL query error ".$q;
                    
                    
// exit
                    
exit;
                }
            }
            
// exit
            
exit; 
    }
    
// else: success.
    // si no: todo bien
    
else
    {
        
// comprobar si se usa failover
        
if ($failover===true)
        {
            
// sql: update status terminate OK
            // el resultado final es OK
            
$q "UPDATE twitter_poster_control SET status = 1, result = 'Todo OK - All OK', date = '".date("Y-m-d")."' WHERE id = 1";
            
// execute
            
$r mysql_query($q$dbconn);
            
// check -verificar
            
if (mysql_affected_rows($dbconn)!=1)
            {
                
// error
                
echo "MySQL query error ".$q;
                
                
// exit
                
exit;
            }
        } 
    }
    


// end benchmarking
// terminar benchmarking
$time_end microtime_float();
$time $time_end $time_start;

echo 
"ejecutado en ".$time." segundos";
?>