The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use autodie qw(:all);
use WWW::Mechanize;
use Try::Tiny;
use JSON::Any;
use Exobrain;
use Exobrain::Cache;
use utf8::all;

# PODNAME: foursquare
# ABSTRACT: Send foursquare events to the exobrain bus

use constant DEBUG => 0;
use constant LAST_CHECK => 'last_check';

my $exobrain = Exobrain->new;
my $config   = $exobrain->config->{Foursquare};
my $TOKEN    = "oauth_token=$config->{auth_token}&v=20130425";
my $BASE     = 'https://api.foursquare.com/v2';

# Setting a stack_depth of zero should disable mech history,
# which may fix the memory leak in GH #7

my $mech = WWW::Mechanize->new( stack_depth => 0 );

my $json = JSON::Any->new;

my $cache = Exobrain::Cache->new(namespace => 'foursquare');
my $bus   = $exobrain->pub;

my $last_check = $cache->compute(LAST_CHECK, undef, sub { time() } );

# Debug switch is a hack to fetch last 2 hours of activity.
if ($ARGV[0] eq '-d') {
    $last_check = time() - 7200;
}

warn("$0: last check at $last_check\n") if DEBUG;

while (1) {

    # Record when we're making our call.
    my $checktime = time();

    warn "Checking with a checktime of $checktime\n" if DEBUG;

    try {
        $mech->get("$BASE/checkins/recent?afterTimestamp=$last_check&$TOKEN");
    }
    catch {
        warn "No connection, or connection failed: $_";
        sleep(60);
        next;
    };

    # If we've made our call successfully, then cache it and update
    # for our next iteration.
    $cache->set(LAST_CHECK, $checktime);
    $last_check = $checktime;

    my $checkins = $json->decode($mech->content)->{response}{recent};

    # Checkins come in most-recent first, so we reverse them and make
    # them chronological.

    foreach my $checkin (reverse @$checkins) {
        my $name = ( $checkin->{user}{firstName} // "" ) . " "
                 . ( $checkin->{user}{lastName}  // "" );

        my $time = localtime($checkin->{createdAt});

        my $user = $checkin->{user}{id};

        warn "Displaying checkin at $checkin->{venue}{name} by $name\n"
            if DEBUG;

        my $packet = $exobrain->measure('Geo',
            source   => 'Foursquare',
            timestamp => $checkin->{createdAt},
            is_me    =>  ($checkin->{user}{relationship} eq 'self'),
            user     => $user,
            user_name => $name,
            message  => $checkin->{shout} // "",
            poi      => {
                name => $checkin->{venue}{name},
                id   => $checkin->{venue}{id},
                lat  => $checkin->{venue}{location}{lat},
                long => $checkin->{venue}{location}{lng},
            },
            raw      => $checkin,
        );
    }

    sleep(60);
}

__END__

=pod

=head1 NAME

foursquare - Send foursquare events to the exobrain bus

=head1 VERSION

version 1.07

=head1 AUTHOR

Paul Fenwick <pjf@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by Paul Fenwick.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut