Ignore:
Timestamp:
Sep 20, 2011, 11:15:32 PM (13 years ago)
Author:
Edward Z. Yang <ezyang@mit.edu>
Branches:
master, release-1.10, release-1.9
Children:
a4ae221
Parents:
65c2b3c
git-author:
Edward Z. Yang <ezyang@mit.edu> (06/22/11 21:53:17)
git-committer:
Edward Z. Yang <ezyang@mit.edu> (09/20/11 23:15:32)
Message:
Improve docs, error handling and refactor.

Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
File:
1 edited

Legend:

Unmodified
Added
Removed
  • perl/modules/Facebook/lib/BarnOwl/Module/Facebook/Handle.pm

    r65c2b3c r01d186f  
    3535use Date::Parse;
    3636use POSIX;
     37use Ouch;
    3738
    3839use Scalar::Util qw(weaken);
     
    6566#   comments less frequently than polling for new posts.
    6667
    67 sub fail {
    68     my $self = shift;
    69     my $msg  = shift;
    70     undef $self->{facebook};
    71     die("[Facebook] Error: $msg\n");
    72 }
    73 
    7468sub new {
    7569    my $class = shift;
     
    8377        # but we can't assume that the BarnOwl lives on a publically
    8478        # addressable server (XXX maybe we can setup an option for this.)
    85         'last_friend_poll' => 0,
    8679        'friend_timer' => undef,
    8780
    8881        # Initialized with our 'time', but will be synced to Facebook
    8982        # soon enough. (Subtractive amount is just to preseed with some
    90         # values.)
    91         'last_poll' => time - 60 * 60 * 24 * 2,
     83        # values.) XXX Remove subtraction altogether.
     84        'last_poll' => time - 60 * 60,
    9285        'timer' => undef,
    9386
     
    9992        # $fb->authorize, but at time of writing (1.0300) they didn't support
    10093        # the response_type parameter.
    101         # 'login_url' => 'https://www.facebook.com/dialog/oauth?client_id=235537266461636&scope=read_stream,read_mailbox,publish_stream,offline_access&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token',
     94        # 'login_url' => 'https://www.facebook.com/dialog/oauth?client_id=235537266461636&scope=read_stream,read_mailbox,publish_stream,offline_access,read_friendlists,rsvp_event,user_events&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token',
    10295        # minified to fit in most terminal windows.
    103         'login_url' => 'http://goo.gl/yA42G',
     96        # Be careful about updating these values, since BarnOwl will not
     97        # notice that it is missing necessary permissions until it
     98        # attempt to perform an operation which fails due to lack of
     99        # permissions.
     100        'login_url' => 'http://goo.gl/rcM9s',
    104101
    105102        'logged_in' => 0,
     
    164161}
    165162
     163sub check_result {
     164    my $self = shift;
     165    if (kiss 400) {
     166        # Ugh, no easy way of accessing the JSON error type
     167        # which is OAuthException.
     168        $self->{logged_in} = 0;
     169        $self->facebook_do_auth;
     170        return 0;
     171    } elsif (hug) {
     172        my $code = $@->code;
     173        warn "Poll failed with $code: $@";
     174        return 0;
     175    }
     176    return 1;
     177}
     178
    166179sub poll_friends {
    167180    my $self = shift;
     
    171184
    172185    my $friends = eval { $self->{facebook}->fetch('me/friends'); };
    173     if ($@) {
    174         warn "Poll failed $@";
    175         return;
    176     }
    177 
    178     $self->{last_friend_poll} = time;
     186    return unless $self->check_result;
     187
    179188    $self->{friends} = {};
    180189
     
    195204            # The most recent one.)  Since getting this information
    196205            # involves extra queries, there are also caching and
    197             # efficiency concerns.
    198             #   We may want a facility for users to specify custom
     206            # efficiency concerns (though hopefully you don't have too
     207            # many friends with the same name).  Furthermore, accessing
     208            # this information requires a pretty hefty extra set of
     209            # permissions requests, which we don't currently ask for.
     210            #   It may just be better to let users specify custom
    199211            # aliases for Facebook users, which are added into this
    200212            # hash.  See also username support.
     
    213225    # query, it would require a rather expensive set of queries. We
    214226    # might try to preserve old data, but all-in-all it's a bit
    215     # complicated, so we don't bother.
     227    # complicated.  One possible way of fixing this is to construct a
     228    # custom FQL query that joins the friends table and the users table.
    216229}
    217230
     
    219232    my $self = shift;
    220233
    221     #return unless ( time - $self->{last_poll} ) >= 60;
    222234    return unless BarnOwl::getvar('facebook:poll') eq 'on';
    223235    return unless $self->{logged_in};
    224 
    225     #BarnOwl::message("Polling Facebook...");
    226236
    227237    # XXX Oh no! This blocks the user interface.  Not good.
     
    237247             ->from("my_news")
    238248             # Not using this, because we want to pick up comment
    239              # updates. We need to manually de-dup, though.
     249             # updates. We need to manually de-duplicate, though.
    240250             # ->where_since( "@" . $self->{last_poll} )
     251             # Facebook doesn't actually give us that many results.
     252             # But it can't hurt to ask!
    241253             ->limit_results( 200 )
    242              ->request()
    243              ->as_hashref()
     254             ->request
     255             ->as_hashref
    244256    };
    245     if ($@) {
    246         warn "Poll failed $@";
    247         return;
    248     }
     257    return unless $self->check_result;
    249258
    250259    my $new_last_poll = $self->{last_poll};
     
    262271        }
    263272
    264         # XXX Need to somehow access Facebook's user hiding
    265         # mechanism
    266 
    267273        # There can be multiple recipients! Strange! Pick the first one.
    268274        my $name    = $post->{to}{data}[0]{name} || $post->{from}{name};
     
    270276        my $post_id  = $post->{id};
    271277
     278        my $topic;
    272279        if (defined $old_topics->{$post_id}) {
    273             $self->{topics}->{$post_id} = $old_topics->{$post_id};
     280            $topic = $old_topics->{$post_id};
     281            $self->{topics}->{$post_id} = $topic;
    274282        } else {
    275283            my @keywords = keywords($post->{name} || $post->{message});
    276             my $topic = $keywords[0] || 'personal';
     284            $topic = $keywords[0] || 'personal';
    277285            $topic =~ s/ /-/g;
    278286            $self->{topics}->{$post_id} = $topic;
     
    292300                body      => $self->format_body($post),
    293301                post_id   => $post_id,
    294                 topic     => $self->get_topic($post_id),
     302                topic     => $topic,
    295303                time      => asctime(localtime $created_time),
    296304                # XXX The intent is to get the 'Comment' link, which also
     
    302310        }
    303311
    304         # This will have funky interleaving of times (they'll all be
    305         # sorted linearly), but since we don't expect too many updates between
     312        # This will interleave times (they'll all be organized by parent
     313        # post), but since we don't expect too many updates between
    306314        # polls this is pretty acceptable.
    307315        my $updated_time = str2time($post->{updated_time});
     
    320328                    direction => 'in',
    321329                    body      => $comment->{message},
    322                     post_id    => $post_id,
    323                     topic     => $self->get_topic($post_id),
     330                    post_id   => $post_id,
     331                    topic     => $topic,
    324332                    time      => asctime(localtime $comment_time),
    325333                   );
     
    355363}
    356364
     365# Invariant: we don't become logged out between entering text field
     366# and actually processing the request.  XXX I don't think this actually
     367# holds, but such a case would rarely happen.
     368
    357369sub facebook {
    358370    my $self = shift;
     
    361373    my $msg = shift;
    362374
    363     if (!defined $self->{facebook} || !$self->{logged_in}) {
    364         BarnOwl::admin_message('Facebook', 'You are not currently logged into Facebook.');
    365         return;
    366     }
    367375    if (defined $user) {
    368376        $user = $self->{friends}{$user} || $user;
    369         $self->{facebook}->add_post( $user )->set_message( $msg )->publish;
     377        eval { $self->{facebook}->add_post( $user )->set_message( $msg )->publish; };
     378        return unless $self->check_result;
    370379    } else {
    371         $self->{facebook}->add_post->set_message( $msg )->publish;
     380        eval { $self->{facebook}->add_post->set_message( $msg )->publish; };
     381        return unless $self->check_result;
    372382    }
    373383    $self->sleep(0);
     
    380390    my $msg = shift;
    381391
    382     $self->{facebook}->add_comment( $post_id )->set_message( $msg )->publish;
     392    eval { $self->{facebook}->add_comment( $post_id )->set_message( $msg )->publish; };
     393    return unless $self->check_result;
    383394    $self->sleep(0);
    384395}
     
    388399
    389400    my $url = shift;
     401
    390402    # http://www.facebook.com/connect/login_success.html#access_token=TOKEN&expires_in=0
    391403    $url =~ /access_token=([^&]+)/; # XXX Ew regex
     404
     405    if (!defined $1) {
     406        BarnOwl::message("Invalid URL.");
     407        return;
     408    }
    392409
    393410    $self->{cfg}->{token} = $1;
     
    402419    if ( ! defined $self->{cfg}->{token} ) {
    403420        BarnOwl::admin_message('Facebook', "Login to Facebook at ".$self->{login_url}
    404             . "\nand run command ':facebook-auth URL' with the URL you are redirected to.");
     421            . "\nand run command ':facebook-auth URL' with the URL you are redirected to."
     422            . "\n\nWhat does Barnowl use these permissions for?  As a desktop"
     423            . "\nmessaging application, we need persistent read/write access to your"
     424            . "\nnews feed and your inbox.  Other permissions are for pending"
     425            . "\nfeatures: we intend on adding support for event streaming, RSVP,"
     426            . "\nand BarnOwl filtering on friend lists."
     427        );
    405428        return 0;
    406429    }
    407430    $self->{facebook}->access_token($self->{cfg}->{token});
    408431    # Do a quick check to see if things are working
    409     my $result = eval { $self->{facebook}->fetch('me'); };
     432    my $result = eval { $self->{facebook}->query()->find('me')->select_fields('name')->request->as_hashref; };
    410433    if ($@) {
    411434        BarnOwl::admin_message('Facebook', "Failed to authenticate! Login to Facebook at ".$self->{login_url}
     
    421444}
    422445
    423 sub get_topic {
    424     my $self = shift;
    425 
    426     my $post_id = shift;
    427 
    428     return $self->{topics}->{$post_id} || 'personal';
    429 }
    430 
    4314461;
Note: See TracChangeset for help on using the changeset viewer.