Annotation of foursquare/foursquare.pl, revision 1.1.1.1

1.1       nick        1: #!/usr/bin/perl -wT
                      2: 
                      3: =begin comment info
                      4: +------------------------------------------------------------------------------
                      5: |
                      6: | See end of script for comments and 'pod2man foursquare.pl | nroff -man' to
                      7: | view man page or pod2text foursquare.pl for plain text.
                      8: |
                      9: | The core submit to FourScore and some concepts such as randomzing some 
                     10: | items to avoid looking automated were taken from Mayank Lahiri's code 
                     11: | found on his web site here:
                     12: |      http://compbio.cs.uic.edu/~mayank/4sq.html
                     13: |
                     14: |   Nicholas DeClario <nick@demandred.dyndns.org>
                     15: |   August 2010
                     16: |      $Id$
                     17: |
                     18: +------------------------------------------------------------------------------
                     19: =end comment
                     20: =cut
                     21: BEGIN {
                     22:         delete @ENV{ qw(IFS CDPATH ENV BASH_ENV PATH) };
                     23:         $ENV{'PATH'} = "/bin:/usr/bin";
                     24:        $|++;
                     25:       }
                     26: 
                     27: use strict;
                     28: use Getopt::Long;
                     29: use Pod::Usage;
                     30: use Data::Dumper;
                     31: use IO::Socket;
                     32: use MIME::Base64;
                     33: 
                     34: my %opts  = &fetchOptions( );
                     35: my $vb    = $opts{'verbose'} || 0;
                     36: my $dbf   = $opts{'db'} || &findDBLocation( ) || exit;
                     37: my $locs  = &readLocations( $dbf ) || exit;
                     38: my $email = "nick\@declario.com";
                     39: my $up    = "bmlja0BkZWNsYXJpby5jb206MzIxd2FmZmxlMQ==";
                     40: 
                     41: srand;
                     42: 
                     43: ##
                     44: ## Generate a new username/email and password
                     45: ## in base64 encoding and exit.
                     46: ##
                     47: if ( $opts{'genup'} )
                     48: {
                     49:        print "Base64 encoded username/pass: " . &genup( ) . "\n";
                     50:        exit( 0 );
                     51: }
                     52: 
                     53: ##
                     54: ## Confirm we were handed a valid location
                     55: ##
                     56: if ( ! defined $locs->{$opts{'location'}} ) 
                     57: {
                     58:        print STDERR "ERROR: Invalid Location: " . $opts{'location'} . "\n";
                     59:        exit( 1 );
                     60: }
                     61: 
                     62: &displayStatus( $vb );
                     63: 
                     64: my $results = &postToFourSquare( );
                     65: print "Result: $results\n" if ( $opts{'verbose'} );
                     66: 
                     67: exit( 0 );
                     68: 
                     69: ###############################################################################
                     70: ##
                     71: ##  &postToFourSquare( );
                     72: ##
                     73: ###############################################################################
                     74: sub postToFourSquare
                     75: {
                     76:        my $result = 0;
                     77: 
                     78:        ##
                     79:        ## Put a delay of up to 10 minutes so we don't look like
                     80:        ## like an automated bot.
                     81:        ##
                     82:        print STDOUT "Sleeping...\n" if (   $opts{'verbose'} &&
                     83:                                        ! $opts{'nosleep'} );
                     84:        sleep( rand( ) * 400 ) if ( ! $opts{'nosleep'} );
                     85:        
                     86:        ##
                     87:        ## Set up our post to the FourSquare server
                     88:        ##
                     89:        my $sock = IO::Socket::INET->new( PeerAddr => 'api.foursquare.com', 
                     90:                                          PeerPort => 80, 
                     91:                                          Proto    => 'tcp', 
                     92:                                          Type     => SOCK_STREAM
                     93:                                        ) or die;
                     94: 
                     95:        my $str = "vid=" . $locs->{$opts{'location'}}{'vid'} . 
                     96:                  "&private=0&geolat=" . $locs->{$opts{'location'}}{'lat'} .
                     97:                  "&geolong=" . $locs->{$opts{'location'}}{'long'};
                     98: 
                     99:        print $sock "POST /v1/checkin HTTP/1.1\r\n"
                    100:             . "Host: api.foursquare.com\r\nUser-Agent: "
                    101:             . "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG01B) "
                    102:            . "AppleWebKit/533.1 (KHTML, like Gecko)"
                    103:             . "Version/4.0 Mobile Safari/533.1\r\nContent-Type: "
                    104:             . "application/x-www-form-urlencoded\r\nAuthorization: Basic "
                    105:             . "$up\r\nContent-length: ", length( $str ) + 2, "\r\n\r\n$str\r\n";
                    106: 
                    107:        $result = <$sock>;
                    108:        
                    109:        chomp $result;
                    110: 
                    111:        return $result;
                    112: }
                    113: 
                    114: ###############################################################################
                    115: ## 
                    116: ## &readLOcations( $file );
                    117: ##
                    118: ##   Read in the locations database.  The format of the database is as 
                    119: ##  as follows: 
                    120: ##
                    121: ##     id, venue id, description, longitutde, latitude
                    122: ##
                    123: ##  The venue ID is required and found vie FourSquares website.  
                    124: ##
                    125: ##  Everything will be pushed in to an hash with 'id' as the key.
                    126: ##
                    127: ###############################################################################
                    128: sub readLocations 
                    129: {
                    130:        my $file    = shift || 0;
                    131:        my %loc     = ( );
                    132:        my @deletes = ( );
                    133: 
                    134:        if ( ! $file ) 
                    135:        {
                    136:                print STDERR "ERROR: Filename of location database missing!\n";
                    137:                return 0;
                    138:        }       
                    139: 
                    140:        open( DB, "<$file" ) or die( "ERROR: Failed to open $file: $!\n" );
                    141:                while( <DB> ) 
                    142:                {
                    143:                        chomp;
                    144: 
                    145:                        ##
                    146:                        ## Ignore Comments and invalid fields
                    147:                        ##
                    148:                        next if ( m/^#/ );      
                    149:                        next if ( ! m/(?:.*,){4}/ );
                    150: 
                    151:                        ##
                    152:                        ## Read in fields
                    153:                        ##
                    154:                        my ( $key, @fields ) = split( /,/, $_ );
                    155:                        $loc{$key}{'vid'}  = $fields[0] || 0;
                    156:                        $loc{$key}{'desc'} = $fields[1] || "N/A";
                    157:                        $loc{$key}{'long'} = $fields[2] || 0;
                    158:                        $loc{$key}{'lat'}  = $fields[3] || 0;
                    159: 
                    160:                        ##
                    161:                        ## We don't want to look like a bot, so we'll
                    162:                        ## fudge our long and lat a tick
                    163:                        ##
                    164:                        $loc{$key}{'lat'}  += rand() * 0.0001 - 0.00005;
                    165:                        $loc{$key}{'long'} += rand() * 0.0001 - 0.00005;
                    166:        
                    167:                        ##
                    168:                        ##  Search for missing fields
                    169:                        ##
                    170:                        foreach my $k ( keys %{ $loc{ $key } } )
                    171:                        {
                    172:                                if ( ! $loc{$key}{$k} )
                    173:                                {       
                    174:                                        print STDERR "WARNING: " . $key .
                    175:                                             " has an invalid field: $k\n" .
                    176:                                             "This location will be removed.\n";
                    177:                                        push @deletes, $key;
                    178:                                }
                    179:                        }
                    180:                }
                    181:        close( DB );
                    182: 
                    183:        map { delete $loc{$_}; } @deletes;
                    184: 
                    185:        print STDERR "ERROR: No valid locatons found in DB!\n"
                    186:                if ( ! %loc );
                    187: 
                    188:        return \%loc;
                    189: }
                    190: 
                    191: ###############################################################################
                    192: ##
                    193: ## my $database_file_path = &findDBLocation( );
                    194: ##
                    195: ##  If no file path for the GPS locations is given, try and figure out 
                    196: ##  where it could be.  
                    197: ##
                    198: ###############################################################################
                    199: sub findDBLocation 
                    200: {
                    201:        my @locations = qw| /etc /etc/foursquare /opt/foursquare . ~ |;
                    202:        my @filenames = qw| fs_locations fs_locations.txt fs_locations.db |;
                    203: 
                    204:        foreach my $loc ( @locations ) 
                    205:        {
                    206:                map { return $loc . "/" . $_ if ( -f $loc . "/" . $_ ) } 
                    207:                        @filenames;
                    208:        }
                    209: 
                    210:        print STDERR "ERROR: Failed to locate foursquare locations database.\n";
                    211: 
                    212:        return 0;
                    213: }
                    214: 
                    215: ###############################################################################
                    216: #
                    217: # &displayStatus( $verbose )
                    218: #
                    219: ###############################################################################
                    220: sub displayStatus
                    221: {
                    222:        my $verbose = shift || 0;
                    223: 
                    224:        print "Using database: $dbf\n";
                    225:                     
                    226:        map 
                    227:        { 
                    228:                print sprintf( "%-10s: %s\n", $_, 
                    229:                                $locs->{$opts{'location'}}{$_} );
                    230:        } keys %{ $locs->{$opts{'location'}} };
                    231: }
                    232: 
                    233: ###############################################################################
                    234: ##
                    235: ## &sendmail( %mail );
                    236: ##
                    237: ###############################################################################
                    238: sub sendmail
                    239: {
                    240:        my $mail = shift || return 0;
                    241: 
                    242: }
                    243: 
                    244: ###############################################################################
                    245: ###############################################################################
                    246: sub genup
                    247: {
                    248:        ##
                    249:        ## Prompt user for email/username and password
                    250:        ##
                    251:        print "Enter e-mail or username: ";
                    252:        my $u = <STDIN>;
                    253:        chomp $u;
                    254:        
                    255:        print "Enter password: ";
                    256:        ## 
                    257:        ## Turn echo off
                    258:        ##
                    259:        my $p = <STDIN>;
                    260:        chomp $p;
                    261:        
                    262:        ##
                    263:        ## Display the results
                    264:        ##
                    265:        return ${\encode_base64($u . ":" . $p)};
                    266: }
                    267: 
                    268: ###############################################################################
                    269: ##
                    270: ## &fetchOptions( );
                    271: ##
                    272: ##      Grab our command line arguments and toss them in to a hash
                    273: ##
                    274: ###############################################################################
                    275: sub fetchOptions {
                    276:         my %opts;
                    277: 
                    278:         &GetOptions(
                    279:                        "database=s"    => \$opts{'db'},
                    280:                        "email"         => \$opts{'email'},
                    281:                        "genup"         => \$opts{'genup'},
                    282:                         "help|?"        => \$opts{'help'},
                    283:                        "location=s"    => \$opts{'location'},
                    284:                         "man"           => \$opts{'man'},
                    285:                        "sleep"         => \$opts{'nosleep'},
                    286:                        "verbose"       => \$opts{'verbose'},
                    287:                    ) || &pod2usage( );
                    288:        &pod2usage( ) if ( ! defined $opts{'location'} &&
                    289:                            ! defined $opts{'genup'} );
                    290:         &pod2usage( ) if defined $opts{'help'};
                    291:         &pod2usage( { -verbose => 2, -input => \*DATA } ) if defined $opts{'man'};
                    292: 
                    293:         return %opts;
                    294: }
                    295: 
                    296: __END__
                    297: 
                    298: =head1 NAME
                    299: 
                    300: masterbuild.pl - blurb
                    301: 
                    302: =head1 SYNOPSIS
                    303: 
                    304: masterbuild.pl [options]
                    305: 
                    306:  Options:
                    307:         --help,?        Display the basic help menu
                    308:        --email,e       Enable sending results via e-mail
                    309:        --genup         Generate base64 encoded username password
                    310:        --location,l    Path to foursquare locations database
                    311:         --man,m         Display the detailed man page
                    312:        --sleep,s       Disable sleep delay
                    313:        --verbose,v     Increase verbosity
                    314: 
                    315: =head1 DESCRIPTION
                    316: 
                    317: =head1 HISTORY
                    318: 
                    319: =head1 AUTHOR
                    320: 
                    321: Nicholas DeClario <nick@declario.com>
                    322: 
                    323: =head1 BUGS
                    324: 
                    325: This is a work in progress.  Please report all bugs to the author.
                    326: 
                    327: =head1 SEE ALSO
                    328: 
                    329: =head1 COPYRIGHT
                    330: 
                    331: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>