Adding location awareness to Ushahidi

This post is for site admins who want to add location awareness to their ushahidi deployment. Location awareness allows ushahidi to know where the visitor is coming from and display them a map local to them. It requires the user to have an ip v4 address. It is not the best solution for this problem but for now it works…

First things first, visit your application/controllers/main.php and comment out these lines

$this->themes->js->latitude = Kohana::config('settings.default_lat');
$this->themes->js->longitude = Kohana::config('settings.default_lon');

Paste this below the lines you have commented out:

include_once 'DetectLocation.php'; // this isn't the best way but it works..
$this->themes->js->latitude = $lat;
$this->themes->js->longitude = $lng;

Next visit ipinfodb.com and grab their mysql database, extract it then import it into your mysql deployment, I used the database name ipinfo.

Create a new php file called DetectLocation.php in the root of your Ushahidi deployment.

Paste this into it

<?php
// Using data from http://ipinfodb.com/ -- this should be in the ipinfo database
// Code by John McLear, all free licenses attached.  Please re-use, modify & redistribute 

$dbuser = 'ipinfo';
// using a psuedo/differnet user because I'm cool like that.
$dbpass = '';
$dbhost = 'localhost';
$dbname = 'ipinfo';

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die                      ('Error connecting to mysql');

mysql_select_db($dbname) or die('Could not select database');

$ipAddress = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
// Get IP Addr of visitor

$query = "SELECT * FROM `ip_group_city` " .
         "WHERE `ip_start` <= INET_ATON( '$ipAddress' ) " .
         "ORDER BY ip_start DESC " .
         "LIMIT 1";

$resultLocation = mysql_query($query);

while ($row = mysql_fetch_array($resultLocation))
{
        $lat = $row['latitude'];
        $lng = $row['longitude'];
}
?>

Test it by visiting your Ushahidi deployment, your map should be centred on your location.

So quick recap. We are using a local mysql database to lookup locations by IP. This is fast, fast is good. It isn’t perfect. Perfect would be better. Feel free to improve upon, change/correct..

Note: You probably also want to do the same changes on reports.php and alerts.php

Only display this months data in Ushahidi

This is a simple hack to make Ushahidi display only the current months worth of data. This is useful if you have a large dataset with no real need to display historical data to your users.

Modify application/controllers/main.php lines 327 onwards.

                /* Commented out by John McLear */
                // $first_month = 1;
                // $last_month = 12;

                /* Added by John McLear as to only show the current month of data */
                $first_month = date('m');
                $last_month = date('m');
                /* End of new code */

                $i = 0;

                foreach ($query as $data)
                {
                        $date = explode('-',$data->dates);

                        $year = $date[0];
                        $month = $date[1];

                        /* Added by John McLear */
                        // Only includes from the month we are in now, yes this sucks but it works
                        if ($month == $first_month){

                                // Set first year
                                if($i == 0)
                                {
                                        $first_year = $year;
                                        $first_month = $month;
                                }

                                // Set last dates
                                $last_year = $year;
                                $last_month = $month;
                        }

                        $i++;
                }

Ushahidi post tweets to API php example

The below code takes an rss search result from twitter, detects the authors location then posts the information to Ushahidi via the API.

Application I used it inMy School Closures for detecting people who tweet about school closures.  Unfortunately I have to use pipes for the location builder which isn’t elegant as Yahoo Pipes sucks and I wish I never started playing with it.  Feel free to play with the pipe I created to get geo location information from a location name, it is the pipe that has the json_decode.

You will need mysql and a table for the guids (this stops us from spamming twitter for authors we have already located). Make sure you change the configuration settings and create a table in mysql.

The method is simple, the code isn’t pretty and will require polishing but here it is:

<pre>
<?php
//CONFIGURE THE SETTINGS BELOW
//twitter settings
$twitterusername = "mytwitteraccount";
$twitterpassword = "apasswordgoeshere";

//database settings
$host = "databasehostname";
$user = "databaseusername";
$pass = "databasepassword";
$dbname = 'databasename';

// You should create a table called tweetguids in your database
$tablename = "tweetguids";

// Change the below feed to a rss feed similar to below
$rssurl = "http://pipes.yahoo.com/pipes/pipe.run?_id=a9663ebc09e69b9195fb2407fba9f2bc&_render=rss";

// END OF CONFIG

$conn = mysql_connect($host, $user, $pass) or die                      ('Error connecting to mysql');
mysql_select_db($dbname);

ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');
error_reporting(E_ALL);

$rss = simplexml_load_file($rssurl) or die("failure");
$count = 0;
foreach ($rss->channel as $chan)
{
$time = $chan->pubDate;
}
foreach ($rss->channel as $chan){$time = $chan->pubDate;}
foreach ($rss->channel->item as $item)
        {
        // only do first 10 records
        if ($count < 10)
                {
                $foundguid=0;
                $guidnew=$item->guid;
                // Check to see if guid exists in db already
                $sql="SELECT * FROM $tablename where guid = \"$guidnew\"";
                $result=mysql_query($sql, $conn);
                while ($row=mysql_fetch_array($result))
                        {
                        $foundguid=1;
                        echo "Foundguid: $foundguid";
                        }
                if($foundguid==1)
                        {
                        echo "We found an alredy existing guid...";
                        }
else
                        {
                        $count = $count + 1;
                        $task="report";
                        $incident_title=$item->title;
                        $guidnew=$item->guid;
                        $incident_title=str_replace(" ","+",$incident_title);
                        $incident_description=$item->description;
                        $incident_description=str_replace(" ","+",$incident_description);
                        $incident_date=date("m/d/Y",$time);
                        $incident_hour=date("H",$time);
                        $incident_minute=date("i",$time);
                        $incident_ampm=date("a",$time);
                        $incident_category="Possible Closure";
                        $location_name="Unknown";
                        $author = $item->author;
                        $author = str_replace(" ","+",$author);
                        $pos = strpos($author,"+");
                        //$author = substr($author,0,$pos);
                        $author = str_ireplace("http://twitter.com/","",$author);
                        $url = "http://$twitterusername:$twitterpassword@api.twitter.com/1/users/lookup.xml?screen_name=$author";
                        //echo $url;
                        $output = simplexml_load_file($url) or die("badauth");
                        foreach ($output->user as $item)
                                {
                                // Get the values out of the XML
                                $location=$item->location;
                                // Clean up the location
                                $location=str_ireplace("-",",",$location);
                                $location=str_ireplace(" ",",",$location);
//                              $location=preg_replace("/[^a-zA-Z0-9\s]/", "", $location);
                                echo "<br/><b>Location content: $location<br/>";
                                // Pass the location to yahoo pipe
                                $location = str_ireplace(" ","",$location);
                                //echo "<br/>Loc: $location";
                                $locationurl = "http://pipes.yahoo.com/pipes/pipe.run?_id=03539616e4cdd62eb15ed26b81e3041e&_render=json&q=$location";

                                 $ch = curl_init();
                                curl_setopt($ch, CURLOPT_URL, $locationurl);
                                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

                                //make the request
                                $json = curl_exec($ch);
                                $arr = (json_decode($json,true));
                                $blah = $arr['value']['items'][0]['name']['loc'];
                                //print_r($blah);
                                $latitude = $blah['lat'];
                                $longitude = $blah['lon'];
                                $location_name = $blah['city'];
                        }

                        $incident_description="Closure reported from twitter";
                        $url = "task=report&incident_title=$incident_title&incident_description=$incident_description&incident_date=$incident_date&incident_hour=$incident_hour&incident_minute=$incident_minu$
                        $posturl = "http://myschoolclosures.com/ushahidi/api";
                        $Curl_Session = curl_init($posturl);
                         curl_setopt ($Curl_Session, CURLOPT_POST, 1);
                         curl_setopt ($Curl_Session, CURLOPT_POSTFIELDS,
                        $url);
                        curl_setopt ($Curl_Session, CURLOPT_FOLLOWLOCATION, 1);
                        curl_exec ($Curl_Session);
                        curl_close ($Curl_Session);
                        //Write to the database
                        $sqlgo="INSERT INTO $tablename VALUES (\"$guidnew\")";
                        $result=mysql_query($sqlgo, $conn);
                }
        }
        //Write anything else to DB just in case anything trails behind
        $sql="INSERT INTO $tablename VALUES (\"$guidnew\")";
        $result=mysql_query($sql, $conn);
        $row=mysql_fetch_array($result);
        //echo "<br/>$sql<br/>";
}
?>