Destult can now act as a twitter client.
authorpdbogen <pdbogen@088b83a4-0077-4247-935c-42ec02c2848b>
Tue, 21 Apr 2009 15:04:58 +0000 (15:04 +0000)
committerpdbogen <pdbogen@088b83a4-0077-4247-935c-42ec02c2848b>
Tue, 21 Apr 2009 15:04:58 +0000 (15:04 +0000)
git-svn-id: https://www.cernu.us/~pdbogen/svn/destult2@92 088b83a4-0077-4247-935c-42ec02c2848b

commands.yaml

index 97e3aa0..d158ef4 100644 (file)
@@ -52,21 +52,29 @@ CLASSIFY: |-
   sub {
     my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
     my( $cmd, $level ) = split( / /, $what, 2 );
-    unless( $level =~ /^[0-9]$/ ) {
+    unless( !($level) || $level =~ /^[0-9]$/ ) {
        $kernel->post( $src, $replypath, "Access level should be a non-negative integer.", $dest );
        return;
     }
-    if( exists( $heap->{ 'commands' }->{ uc( $cmd ) } ) ) {
-       $heap->{ 'cmdaccess' }->{ uc( $cmd ) } = $level;
+    if( defined $level ) {
+      if( exists( $heap->{ 'commands' }->{ uc( $cmd ) } ) ) {
+        $heap->{ 'cmdaccess' }->{ uc( $cmd ) } = $level;
         DumpFile( "cmdaccess.yaml", $heap->{ 'cmdaccess' } );
         $kernel->post( $src, $replypath, "Set.", $dest );
-    } elsif( exists( $heap->{ 'db' }->{ uc( $cmd ) } ) ) {
-      $heap->{ 'factoidAccess' } = {} unless exists $heap->{ 'factoidAccess' };
-      $heap->{ 'factoidAccess' }->{ uc( $cmd ) } = $level;
-      DumpFile( 'factoidAccess.yaml', $heap->{ 'factoidAccess' } );
-      $kernel->post( $src, $replypath, "Set.", $dest );
+      } elsif( exists( $heap->{ 'db' }->{ uc( $cmd ) } ) ) {
+        $heap->{ 'factoidAccess' } = {} unless exists $heap->{ 'factoidAccess' };
+        $heap->{ 'factoidAccess' }->{ uc( $cmd ) } = $level;
+        DumpFile( 'factoidAccess.yaml', $heap->{ 'factoidAccess' } );
+        $kernel->post( $src, $replypath, "Set.", $dest );
+      } else {
+        $kernel->post( $src, $replypath, "'$cmd' not found.", $dest );
+      }
     } else {
-       $kernel->post( $src, $replypath, "'$cmd' not found.", $dest );
+      if( exists( $heap->{ 'cmdaccess' }->{ uc( $cmd ) } ) ) {
+        $kernel->post( $src, $replypath, uc( $cmd )." is level ".$heap->{ 'cmdaccess' }->{ uc( $cmd ) }, $dest );
+      } else {
+        $kernel->post( $src, $replypath, uc( $cmd )." is not classified.", $dest );
+      }
     }
   }
 
@@ -81,6 +89,7 @@ DECLASSIFY: |-
     for my $list (keys %lists) {
       if( exists( $heap->{ $list } ) && exists( $heap->{ $list }->{ uc( $what ) } ) ) {
         delete( $heap->{ $list }->{ uc( $what ) } );
+        DumpFile( $list.'.yaml', $heap->{ $list } );
         $kernel->post( $src, $replypath, "'$what' removed from ".$lists{ $list }." access list.", $dest );
         $found = 1;
       }
@@ -309,15 +318,21 @@ SETPASSWORD: |-
 CONFIG: |-
   sub {
     my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
-    my( $subj, $predicate ) = split( / /, $what, 2 );
-    if( $predicate ) {
-      $Destult::config{ uc( $subj ) } = $predicate;
-      DumpFile( "config.yaml", \%Destult::config );
-      $kernel->post( $src, $replypath, "Okay, $who.", $dest );
-    } elsif( exists( $Destult::config{ uc( $subj ) } ) ) {
-      $kernel->post( $src, $replypath, "$subj is '".$Destult::config{ uc( $subj ) }."'.", $dest );
+    if( $what ) {
+      my( $subj, $predicate ) = split( / /, $what, 2 );
+      if( $predicate ) {
+        $Destult::config{ uc( $subj ) } = $predicate;
+        DumpFile( "config.yaml", \%Destult::config );
+        $kernel->post( $src, $replypath, "Okay, $who.", $dest );
+      } elsif( exists( $Destult::config{ uc( $subj ) } ) ) {
+        $kernel->post( $src, $replypath, "$subj is '".$Destult::config{ uc( $subj ) }."'.", $dest );
+      } else {
+        $kernel->post( $src, $replypath, "$subj is not found.", $dest );
+      }
     } else {
-      $kernel->post( $src, $replypath, "$subj is not found.", $dest );
+      for my $key ( keys %Destult::config ) {
+        $kernel->post( $src, $replypath, "$key: ".$Destult::config{ $key }, $dest );
+      }
     }
   }
 
@@ -439,8 +454,8 @@ DICTCLEAN: |-
 
 DICT: |-
   sub {
-    require WWW::Search;
-    require WWW::Search::UrbanDictionary;
+    use WWW::Search;
+    use WWW::Search::UrbanDictionary;
 
     my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
     if( $what =~ /^$/ ) {
@@ -1879,3 +1894,144 @@ TITLE: |-
       }
     }
   }
+
+TWITTERCLEAR: |-
+  sub {
+    my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
+    unlink( 'twitterUsers.yaml' );
+    delete( $heap->{ 'twitterUsers' } );
+    $kernel->post( $src, $replypath, "Twitter user database cleared.", $dest );
+  }
+
+TWITTER: |-
+  sub {
+    my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
+  
+    use Net::OAuth;
+    use Digest::MD5 qw( md5_hex );
+    use HTTP::Request::Common;
+    use LWP::UserAgent;
+    
+    my $userAgent = LWP::UserAgent->new();
+    my $nonce = md5_hex( time.rand );
+    
+    if( !exists( $heap->{ 'twitterUsers' } ) ) {
+      if( -e 'twitterUsers.yaml' ) {
+        $heap->{ 'twitterUsers' } = LoadFile( 'twitterUsers.yaml' );
+      } else {
+        $heap->{ 'twitterUsers' } = {};
+      }
+    }
+
+    my $len = length $what;
+    if( $len > 140 ) {
+      $kernel->post( $src, $replypath, "Your tweet exceed the 140-character limit by ".($len - 140)." character".($len>141?"s":""), $dest );
+      return;
+    }
+    
+    if( exists( $heap->{ 'twitterUsers' }->{ uc( $who ) } ) ) {
+      if( $heap->{ 'twitterUsers' }->{ uc( $who ) }->{ "state" } == 0 ) {
+        my $oaRequest = Net::OAuth->request( "access token" )->new(
+          consumer_key     => $Destult::config{ "TWITTER_C_K" },
+          consumer_secret  => $Destult::config{ "TWITTER_C_S" },
+          request_url      => 'http://twitter.com/oauth/access_token',
+          request_method   => 'POST',
+          signature_method => 'HMAC-SHA1',
+          timestamp        => time,
+          nonce            => $nonce,
+          token            => $heap->{ 'twitterUsers' }->{ uc( $who ) }->{ "request_token" },
+          token_secret     => $heap->{ 'twitterUsers' }->{ uc( $who ) }->{ "request_secret" },
+        );
+        $oaRequest->sign();
+        my $response = $userAgent->request( POST $oaRequest->to_url() );
+        if( !$response->is_success() ) {
+          print( "TWITTER: Error: ".$response->status_line(), "\n" );
+          $kernel->post( $src, $replypath, "Either you denied Destult access, or some other error occured. Please try again.", $dest );
+          delete $heap->{ 'twitterUsers' }->{ uc( $who ) };
+          DumpFile( "twitterUsers.yaml", $heap->{ 'twitterUsers' } );
+          return;
+        }
+        my $oaResponse = Net::OAuth->response( 'access token' )->from_post_body( $response->content );
+        $heap->{ 'twitterUsers' }->{ uc( $who ) } = {
+          state => 1,
+          token => $oaResponse->token,
+          secret => $oaResponse->token_secret,
+        };
+        $kernel->post( $src, $replypath, "Congratulations! Destult now has a token to access your Twitter account. You shouldn't need to do this again.", $dest );
+        DumpFile( "twitterUsers.yaml", $heap->{ 'twitterUsers' } );
+      }
+      my $oaRequest = Net::OAuth->request( "protected resource" )->new(
+        consumer_key     => $Destult::config{ "TWITTER_C_K" },
+        consumer_secret  => $Destult::config{ "TWITTER_C_S" },
+        request_url      => 'http://twitter.com/statuses/update.json',
+        request_method   => 'POST',
+        signature_method => 'HMAC-SHA1',
+        timestamp        => time,
+        nonce            => $nonce,
+        token            => $heap->{ 'twitterUsers' }->{ uc( $who ) }->{ "token" },
+        token_secret     => $heap->{ 'twitterUsers' }->{ uc( $who ) }->{ "secret" },
+        extra_params => {
+          status => $what
+        }
+      );
+      $oaRequest->sign();
+      my $response = $userAgent->request( POST $oaRequest->to_url() );
+      if( !$response->is_success() ) {
+        print( "TWITTER: Error: ".$response->status_line(), "\n" );
+        if( $response->code == "401" ) {
+          $kernel->post( $src, $replypath, "401 from Twitter: This generally means Destult ".
+                                           "has been de-authorized to update your Twitter ".
+                                           "status. You might consider using ~DETWITTER and ".
+                                           "then re-authorizing through ~TWITTER.", $dest );
+        } else {
+          $kernel->post( $src, $replypath, "I ran into an error updating your Twitter status: ".$response->status_line, $dest );
+        }
+        return;
+      }
+      $kernel->post( $src, $replypath, "Tweet.", $dest );
+    } else {
+      my $oaRequest = Net::OAuth->request( "request token" )->new(
+        consumer_key     => $Destult::config{ "TWITTER_C_K" },
+        consumer_secret  => $Destult::config{ "TWITTER_C_S" },
+        request_url      => 'http://twitter.com/oauth/request_token',
+        request_method   => 'POST',
+        signature_method => 'HMAC-SHA1',
+        timestamp        => time,
+        nonce            => $nonce
+      );
+      
+      $oaRequest->sign();
+      
+      $kernel->post( $src, $replypath, "One moment, I am retrieving a request token..", $dest );
+      my $response = $userAgent->request( POST $oaRequest->to_url() );
+      
+      if( !($response->is_success()) ) {
+        $kernel->post( $src, $replypath, "An error occured while retrieving the request token from Twitter: ".$response->status_line() );
+        return;
+      }
+      
+      my $oaResponse = Net::OAuth->response( 'request token' )->from_post_body( $response->content );
+      $kernel->post( $src, $replypath, "You must grant Destult write access to your Twitter account. ".
+                                       "To do so, please visit: ".
+                                       "http://twitter.com/oauth/authorize?oauth_token=".($oaResponse->token)." ".
+                                       "and then re-run this command.", $dest );
+      $heap->{ 'twitterUsers' }->{ uc( $who ) } = {
+       request_token => $oaResponse->token,
+       request_secret => $oaResponse->token_secret,
+       state => 0
+      };
+      DumpFile( "twitterUsers.yaml", $heap->{ 'twitterUsers' } );
+    }
+  }
+
+DETWITTER: |-
+  sub {
+    my( $kernel, $heap, $who, $what, $src, $dest, $replypath ) = @_;
+    if( exists( $heap->{ 'twitterUsers' }->{ uc( $who ) } ) ) {
+      delete $heap->{ 'twitterUsers' }->{ uc( $who ) };
+      DumpFile( "twitterUsers.yaml", $heap->{ 'twitterUsers' } );
+      $kernel->post( $src, $replypath, "I've discarded my access token for your account.", $dest );
+    } else {
+      $kernel->post( $src, $replypath, "I have no access token for your account.", $dest );
+    }
+  }