<?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"]!=0 && !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"]==2 && !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($ch, CURLOPT_URL, $host);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);

    // 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_pw, urlencode(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_pw, urlencode(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";
?>