Instagram bingo

This is a game that’s perfect for a company event, like our own Helsinki kick off. You get a list with stuff that you’re supposed to capture with your smartphone camera, tag properly and upload to instagram. Some of them are bound to a place, some not. Hard task – more points. In the field you get to see the other teams’ progress, as well as your own, listed and on a map. You also get comments from the web app directly in your instagram feed, telling you if you got points or if the image is no good for some reason, wrong location for instance.

In the backend we have a database with teams, challenges and scores, and a web app connected to the instagram api. The app checks the participants’ feeds for tags included in the game, and compares the challenge geo data to the image location, considering a specified allowed offset in meters.

Our challenges would be something like “Eating a Panda liquorice ice cream in Esplanadin Puisto”. The team would then have to find out what and where Esplanadin Puisto is, try to get there, find a place that sells the particular Panda ice cream, and take the photo. Plus snap a picture of a mullet on the way.

A time frame factor could also be added to the game – “A woman walking into the Arabia Store between 12 and 12.15”

We can make this fun thing happen at your event too. While your staff get loads of fun and team building, your company gets lots of positive social media exposure. Everybody’s happy, for real.

http://perkele.earthpeople.se

Making signed requests with CodeIgniter

Recently we’ve done lots of backends for IOS apps, Flash sites, Facebook apps and such. In most cases, it’s just a matter of responding with JSON to a HTTP request, saving or fetching something from a datasource. The problem is that it’s fairly easy to sniff the request, change a few parameters and submit a forged request. Up until now, we’ve done authentication on an ad hoc basis, but last week i whipped up a simple CodeIgniter library to standardize the way we do this authentication. Here it is.

This is how to work it:
1. Place this file in application/libraries/
2. Load or autoload it
3. In your controller, use this to validate a request:

if($this->checksum->validate()){
    # keep calm and carry on
 }else{
    # respond that the checksum was bad
 }

4. Call your controller with ?checksum= or by passing checksum as a post variable.
5. The value of checksum must be calculated correctly on the client side (IOS app/Flash/etc). Bad requests are logged in application/logs, together with the correct checksum for the request.

This is how it works:
The calucation is done like this:
sha1(‘yourcontroller/yourmethod/?fieldstring|salt);

“fieldstring” is all the post or get variables, formatted like name=value&name2=value2&etc
post and get variables must be sorted on key name (using same algorithm as php ksort).

“salt” is the CodeIgniter encryption key, set in application/config/config.php

Gotchas:
– This method allows the same request to be sent again, as long as it looks exactly the same. It’s pretty easy to make this library take current time into account, but would require that your CodeIgniter install and your external app do a little handshake on init, syncing the app’s timestamp to the server’s. Should you need this functionality, just put a time() somewhere in the sha1 in both the lib and the app.
–  We currently only handle the request methods GET and POST. If you need support for more verbs, you are probably capable of adding it yourself, heh.

(If you end up using this: please share your client code, and let me know so i can put up a link to it from here!)

CodeIgniter/ActiveRecord setup to use master + slave db replication

This is how you can set up CodeIgniter to direct mysql queries to different read/write hosts in your db replicated environment, using a db_slave for your SELECT’s, and a db_master for the INSERT/UPDATE/DELETE queries.

File: application/config/database.php

Specify the different database hosts in the database config file:

< ?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

$active_group = "master";
$active_record = TRUE;

# db_master
$db['master']['hostname'] = "host1";
$db['master']['username'] = "username";
$db['master']['password'] = "password";
$db['master']['database'] = "exampledb";
$db['master']['dbdriver'] = "mysql";
$db['master']['dbprefix'] = "";
$db['master']['pconnect'] = FALSE;
$db['master']['db_debug'] = TRUE;
$db['master']['cache_on'] = FALSE;
$db['master']['cachedir'] = "";
$db['master']['char_set'] = "utf8";
$db['master']['dbcollat'] = "utf8_general_ci";

#db_slave
$db['slave']['hostname'] = "host2";
$db['slave']['username'] = "username";
$db['slave']['password'] = "password";
$db['slave']['database'] = "exampledb";
$db['slave']['dbdriver'] = "mysql";
$db['slave']['dbprefix'] = "";
$db['slave']['pconnect'] = FALSE;
$db['slave']['db_debug'] = TRUE;
$db['slave']['cache_on'] = FALSE;
$db['slave']['cachedir'] = "";
$db['slave']['char_set'] = "utf8";
$db['slave']['dbcollat'] = "utf8_general_ci";
...

File: application/core/My_Model.php

Add this into My_Model:

< ?php

class MY_Model extends CI_Model {
    function __construct(){
        parent::__construct();
	$this->db_master = $this->load->database('default', TRUE);
	$this->db_slave = $this->load->database('default', TRUE);
    }


}

File: application/models/example_model.php

Use the read/write queries in your models like this:

< ?php
class example_model extends MY_Model {

	function example_model()
	{
		parent::MY_Model();
	}

	# read query
	function getSomething()
	{
		$query = $this->db_slave->get('mytable'); // db_slave
		return $query->result();
	}

	# write query
	function insertSomething()
	{
		$this->db_master->insert('mytable', $_POST); // db_master
		return $this->db_master->insert_id();
	}

That´s it!

Fetching WordPress content from CodeIgniter

In a few recent projects we’ve used the excellent WordPress admin for content entry, but built the public facing stuff in CodeIgniter. Making these platforms talk to each other is fairly simple, and this is what we’ve learnt along the way.

– Do not, ever, initialize WordPress to fetch the data.
WordPress is quite the memory hog (compared to CI) and requesting WordPress content via feeds (using the JSON API plugin or such) heavily will bring your server down under load.

– Instead, always query the DB directly.
WordPress data structure is quite simple. But some of the WordPress functions are poorly written, so port them manually rather than just dumping them into CI.

As we’ve used this on a few sites already, it felt like we should wrap this into something generic and reusable. And with Sparks making its way into the CodeIgniter core, the time had come to learn how to wrap reusable CI stuff in sparks. So here we go. Version 0.0.4 of CodeIgniter-WP. There are only a few methods available at the moment, but hey – look at the version number. It will be better.

$this->load->spark('wp/0.0.4');
print_r($this->wp->get_post('blog', 1);
print_r($this->wp->get_installations());
print_r($this->wp->wp_get_recent_posts('blog', array()));
print_r($this->wp->get_post('blog', 1));
print_r($this->wp->get_post_meta('blog', array('post_id' => 1, 'key' => '_edit_last', 'single' => false)));

Download the spark by following the instructions here.

CodeIgniter development site – on live environment

We recently had to set up a development site for an existing CodeIgniter site, and we wanted to do this effortless. Ideal would obviously be to have a separate virtual domain or a separate box but hey, “ideal” isn’t always ideal, heh.

By applying the same principle as in our previous WordPress article on the same topic, this is done in well under 5 minutes. Upload the same /dev folder as in the WordPress case, and make the following modification in the main CodeIgniter index.php file.

Change this:

$system_folder = "system";

to:

if(isset($_COOKIE["dev"])){
	$system_folder = "sysdev";
}else{
	$system_folder = "system";
}

Then copy the /system directory to /sysdev – and that will be your new development docroot. Once you’re ready to release your next version, either copy each file from /sysdev to /system – or simply change the name of /system to /system-OLD and /sysdev to /system.