#!/usr/bin/perl -wT =begin comment info +------------------------------------------------------------------------------ | | See end of script for comments and 'pod2man foursquare.pl | nroff -man' to | view man page or pod2text foursquare.pl for plain text. | | The core submit to FourScore and some concepts such as randomzing some | items to avoid looking automated were taken from Mayank Lahiri's code | found on his web site here: | http://compbio.cs.uic.edu/~mayank/4sq.html | | Nicholas DeClario | August 2010 | $Id: foursquare.pl,v 1.2 2010/09/15 11:34:27 nick Exp $ | +------------------------------------------------------------------------------ =end comment =cut BEGIN { delete @ENV{ qw(IFS CDPATH ENV BASH_ENV PATH) }; $ENV{'PATH'} = "/bin:/usr/bin"; $|++; } use strict; use Getopt::Long; use Pod::Usage; use Data::Dumper; use IO::Socket; use MIME::Base64; my %opts = &fetchOptions( ); my $vb = $opts{'verbose'} || 0; my $dbf = $opts{'db'} || &findDBLocation( ) || exit; my $locs = &readLocations( $dbf ) || exit; my $email = "nick\@declario.com"; my $up = "bmlja0BkZWNsYXJpby5jb206MzIxd2FmZmxlMQ=="; srand; ## ## Generate a new username/email and password ## in base64 encoding and exit. ## if ( $opts{'genup'} ) { print "Base64 encoded username/pass: " . &genup( ) . "\n"; exit( 0 ); } ## ## Confirm we were handed a valid location ## if ( ! defined $locs->{$opts{'location'}} ) { print STDERR "ERROR: Invalid Location: " . $opts{'location'} . "\n"; exit( 1 ); } &displayStatus( ) if ( $vb ); my $results = &postToFourSquare( ); print "Result: $results\n" if ( $opts{'verbose'} ); exit( 0 ); ############################################################################### ## ## &postToFourSquare( ); ## ############################################################################### sub postToFourSquare { my $result = 0; ## ## Put a delay of up to 10 minutes so we don't look like ## like an automated bot. ## print STDOUT "Sleeping...\n" if ( $opts{'verbose'} && ! $opts{'nosleep'} ); sleep( rand( ) * 400 ) if ( ! $opts{'nosleep'} ); ## ## Set up our post to the FourSquare server ## my $sock = IO::Socket::INET->new( PeerAddr => 'api.foursquare.com', PeerPort => 80, Proto => 'tcp', Type => SOCK_STREAM ) or die; my $str = "vid=" . $locs->{$opts{'location'}}{'vid'} . "&private=0&geolat=" . $locs->{$opts{'location'}}{'lat'} . "&geolong=" . $locs->{$opts{'location'}}{'long'}; print $sock "POST /v1/checkin HTTP/1.1\r\n" . "Host: api.foursquare.com\r\nUser-Agent: " . "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG01B) " . "AppleWebKit/533.1 (KHTML, like Gecko)" . "Version/4.0 Mobile Safari/533.1\r\nContent-Type: " . "application/x-www-form-urlencoded\r\nAuthorization: Basic " . "$up\r\nContent-length: ", length( $str ) + 2, "\r\n\r\n$str\r\n"; $result = <$sock>; chomp $result; return $result; } ############################################################################### ## ## &readLOcations( $file ); ## ## Read in the locations database. The format of the database is as ## as follows: ## ## id, venue id, description, longitutde, latitude ## ## The venue ID is required and found vie FourSquares website. ## ## Everything will be pushed in to an hash with 'id' as the key. ## ############################################################################### sub readLocations { my $file = shift || 0; my %loc = ( ); my @deletes = ( ); if ( ! $file ) { print STDERR "ERROR: Filename of location database missing!\n"; return 0; } open( DB, "<$file" ) or die( "ERROR: Failed to open $file: $!\n" ); while( ) { chomp; ## ## Ignore Comments and invalid fields ## next if ( m/^#/ ); next if ( ! m/(?:.*,){4}/ ); ## ## Read in fields ## my ( $key, @fields ) = split( /,/, $_ ); $loc{$key}{'vid'} = $fields[0] || 0; $loc{$key}{'desc'} = $fields[1] || "N/A"; $loc{$key}{'long'} = $fields[2] || 0; $loc{$key}{'lat'} = $fields[3] || 0; ## ## We don't want to look like a bot, so we'll ## fudge our long and lat a tick ## $loc{$key}{'lat'} += rand() * 0.0001 - 0.00005; $loc{$key}{'long'} += rand() * 0.0001 - 0.00005; ## ## Search for missing fields ## foreach my $k ( keys %{ $loc{ $key } } ) { if ( ! $loc{$key}{$k} ) { print STDERR "WARNING: " . $key . " has an invalid field: $k\n" . "This location will be removed.\n"; push @deletes, $key; } } } close( DB ); map { delete $loc{$_}; } @deletes; print STDERR "ERROR: No valid locatons found in DB!\n" if ( ! %loc ); return \%loc; } ############################################################################### ## ## my $database_file_path = &findDBLocation( ); ## ## If no file path for the GPS locations is given, try and figure out ## where it could be. ## ############################################################################### sub findDBLocation { my @locations = qw| /etc /etc/foursquare /opt/foursquare . ~ |; my @filenames = qw| fs_locations fs_locations.txt fs_locations.db |; foreach my $loc ( @locations ) { map { return $loc . "/" . $_ if ( -f $loc . "/" . $_ ) } @filenames; } print STDERR "ERROR: Failed to locate foursquare locations database.\n"; return 0; } ############################################################################### # # &displayStatus( $verbose ) # ############################################################################### sub displayStatus { my $verbose = shift || 0; print "Using database: $dbf\n"; map { print sprintf( "%-10s: %s\n", $_, $locs->{$opts{'location'}}{$_} ); } keys %{ $locs->{$opts{'location'}} }; } ############################################################################### ## ## &sendmail( %mail ); ## ############################################################################### sub sendmail { my $mail = shift || return 0; } ############################################################################### ############################################################################### sub genup { ## ## Prompt user for email/username and password ## print "Enter e-mail or username: "; my $u = ; chomp $u; print "Enter password: "; ## ## Turn echo off ## my $p = ; chomp $p; ## ## Display the results ## return ${\encode_base64($u . ":" . $p)}; } ############################################################################### ## ## &fetchOptions( ); ## ## Grab our command line arguments and toss them in to a hash ## ############################################################################### sub fetchOptions { my %opts; &GetOptions( "database=s" => \$opts{'db'}, "email" => \$opts{'email'}, "genup" => \$opts{'genup'}, "help|?" => \$opts{'help'}, "location=s" => \$opts{'location'}, "man" => \$opts{'man'}, "sleep" => \$opts{'nosleep'}, "verbose" => \$opts{'verbose'}, ) || &pod2usage( ); &pod2usage( ) if ( ! defined $opts{'location'} && ! defined $opts{'genup'} ); &pod2usage( ) if defined $opts{'help'}; &pod2usage( { -verbose => 2, -input => \*DATA } ) if defined $opts{'man'}; return %opts; } __END__ =head1 NAME masterbuild.pl - blurb =head1 SYNOPSIS masterbuild.pl [options] Options: --help,? Display the basic help menu --email,e Enable sending results via e-mail --genup Generate base64 encoded username password --location,l Path to foursquare locations database --man,m Display the detailed man page --sleep,s Disable sleep delay --verbose,v Increase verbosity =head1 DESCRIPTION =head1 HISTORY =head1 AUTHOR Nicholas DeClario =head1 BUGS This is a work in progress. Please report all bugs to the author. =head1 SEE ALSO =head1 COPYRIGHT =cut