root/feedmelinks/lib/FeedMeLinks/Bot.pm

Revision 1441, 24.5 kB (checked in by jm3, 2 years ago)

spam

Line 
1 #!/usr/local/bin/perl
2 package FeedMeLinks::Bot;
3 use strict;
4
5 # $Id$
6
7 require Encode;
8 use Data::Dumper;
9 use Date::Format;
10 use FeedMeLinks::Environment;
11 use File::Temp qw/ :mktemp  /;
12 use HTML::Strip;
13 use HTML::TokeParser;
14 use LWP::UserAgent;
15 use MIME::Base64;
16 use XML::XPath;
17
18 my $logfile = FeedMeLinks::Environment::get_webserver_root() . "/_logs/aim.log";
19 open(LOG, ">>" . $logfile) or die "can't open log $logfile";
20
21 { # flush writes to the log so we see them immediately
22         my $ofh = select LOG;
23         $| = 1;
24         select $ofh;
25 }
26
27 my $num_recent = 5;
28 my $www = get_proxy( FeedMeLinks::Environment::get_bot_puppetmaster_user(), FeedMeLinks::Environment::get_bot_puppetmaster_password());
29 my $site = "http://www." . FeedMeLinks::Environment::get_domain();
30
31 # init
32 sub handle_response {
33         my ($aim, $sender, $message, $away, $sessions_ref ) = @_;
34
35         my $user;
36         # AIM can wrap messages w/ shouty <HTML><FONT>...</FONT></HTML> crap. this strips that
37         $message = strip_html( $message );
38         log_mesg( \*LOG, "debug", "command: $message" );
39
40         # init user
41         my $fml_username = is_user_validated( $sender );
42         $fml_username .= ""; # type coerce
43         if( ! $fml_username ) {
44          if( $sessions_ref->{ $sender }{ "seen_welcome" } == 0 && !( $message =~ m/validate/ )) {
45                         $aim->send_im($sender, h("<b>Hi! I am the Feed Me Links bot!</b>\nType '<b>help</b>' "
46                         . " for more info or click <b><a href='$site/set-up/IM?aim=$sender'>activate</a></b> to start adding links.") );
47                         $sessions_ref->{"$sender"} = build_empty_session( $sender );
48                         $sessions_ref->{ $sender }{ "seen_welcome" } = 1;
49                 }
50         } else {
51                 if( $sessions_ref->{ $sender }{ "seen_welcome" } == 0 ) {
52                         $aim->send_im( $sender, "Welcome back, " .  get_dude() . "!" );
53                         $sessions_ref->{"$sender"} = build_authenticated_session( $fml_username, $sender );
54                         $sessions_ref->{ $sender }{ "seen_welcome" } = 1;
55                 }
56         }
57
58         # COMMAND: ADD LINK ###############################################################
59         if(
60                 $message =~ m/(ftp|gopher|https?):\/\//
61                 || $message =~ m/www\./
62                 || $message =~ m/\.(com|org|net|biz|info|gov|mil|edu|uk|es|jp|mx|it|am|ca|de|nu|tv)\/?$/
63                 ) {
64                 if( $sessions_ref->{ $sender }->{ "validated" } ) {
65                         my $url = $message;
66                         $url =~ s/^add //;
67                         $url = add_prefix( $url );
68
69                         my $name = get_title_for_url( $url );
70                         my $name = $name ? $name : $url;
71                         my $encoded_name = encode( $name );
72                         my $encoded_url = encode( $url );
73                         log_mesg( \*LOG, "add link", "$sender adding $url as $name" );
74
75                         my $response = $sessions_ref->{$sender}->{"proxy"}->get( "$site/api/add?url=$encoded_url&name=$encoded_name", []);
76                         my $xp = XML::XPath->new(xml => $response->content);
77                         my $info = $xp->getNodeText( "/result" );
78
79                         if( $info =~ m/http/ ) {
80                                 my $link_id = $info;
81                                 $link_id =~ s/.*com\///;
82                                 print "< FML server gave us link ID: $link_id\n";
83
84                                 # set our session state
85                                 $sessions_ref->{$sender}->{"last_link"} = $link_id;
86                                 $sessions_ref->{$sender}->{"last_name"} = $name;
87                                 $sessions_ref->{$sender}->{"last_action"} = "added_link";
88                                 $sessions_ref->{$sender}->{"added_tags"} = 0;
89                                 $sessions_ref->{$sender}->{"renamed"} = 0;
90
91                                 log_mesg( \*LOG, "set last_link hash thing to : " . $sessions_ref->{$sender}->{"last_link"} );
92
93                                 $aim->send_im($sender, h("<b>Added</b>:\n<a href='$info'>$name</a>" ));
94                                 $aim->send_im($sender,
95                                         h(
96                                                 get_message( "add_tags") . "\n"
97                                                 . get_message( "rename" ) . "\n"
98                                                 . get_message( "share" )
99                                                 ));
100                         } else {
101                                 if( $info =~ m/Duplicate/ ) {
102                                         $aim->send_im($sender, h("<b>$info</b>" ));
103                                 } else {
104                                         $aim->send_im($sender, h("<b>Oops, the server screwed something up!</b>\n$info" ));
105                                 }
106                                 log_mesg( \*LOG, "error:add link", "$sender adding $url as $name" );
107                         }
108
109                 } else {
110                         # FIXME: should search and say "NN people have added this link -- click activate to add it"
111                         log_mesg( \*LOG, "error:add link", "un-authenticated add request from $sender for $message" );
112                         $aim->send_im($sender, h("To start adding links, please click <b><a href='$site/set-up/IM?aim=$sender'>activate my account</a></b>." ));
113                 }
114                
115         # COMMAND: VALIDATE ###############################################################
116         } elsif( $message =~ m/validate:/ ) {
117
118                         my $claimed_fml_username = $message;
119                         $claimed_fml_username =~ s/validate: //;
120                         my $aim_validation_phrase = $claimed_fml_username; # ordering of these lines is significant!
121                         $aim_validation_phrase =~ s/^.+, //;
122                         $aim_validation_phrase =~ s/<.*$//;
123                         $claimed_fml_username =~ s/,.+$//;
124                         #print "claimed_fml_username: $claimed_fml_username\n";
125                         #print "aim_validation_phrase: $aim_validation_phrase\n";
126                         log_mesg( \*LOG, "validate", "$sender requesting validation with $message" );
127
128                         print "$site/api/backroom/get_im_validation_phrase_for_user&user=$claimed_fml_username\n";
129                 my $response = $www->get(
130                         "$site/api/backroom/get_im_validation_phrase_for_user&user=$claimed_fml_username",
131                         []);
132                 my $xp = XML::XPath->new(xml => $response->content);
133                 my $fml_validation_phrase = $xp->getNodeText("/rest/response");
134                 print "fml_validation_phrase: $fml_validation_phrase\n";
135
136                 if( $fml_validation_phrase eq $aim_validation_phrase ) {
137                         my $response = $www->get(
138                                 "$site/api/backroom/validate_users_im_name&user=$claimed_fml_username",
139                                 []);
140                         $xp = XML::XPath->new(xml => $response->content);
141                         my $validation_response = $xp->getNodeText("/rest/response");
142                         print "validation_response: $validation_response\n";
143
144                         $sessions_ref->{"$sender"} = build_authenticated_session( $claimed_fml_username, $sender );
145
146                         $aim->send_im($sender, "<b>\n\nAll done -- that was easy</b>!\nNow your Feed Me Links account is linked to your "
147                                 . "AIM and you can start using Feed Me Links via AIM. To get started, paste any URL into this window." );
148                 } else {
149                         $aim->send_im($sender, h("Darn, that doesn't match our records. Please try again, or <a href='$site/contact-us?subject=AIM+issues:+'>contact us</a>.") );
150                 }
151
152         # COMMAND: WHO ###############################################################
153         } elsif( $message =~ m/who/ || $message =~ m/lusers/ ) {
154                 my $users = "";
155     for my $user ( keys %$sessions_ref ) {
156                         $users .=
157                         "<a href='$site/"
158                                 . $sessions_ref->{ $user } -> { "fml_username" } . "'>"
159                                 . $sessions_ref->{ $user } -> { "fml_username" }
160                                 ."</a> ($user), ";
161     }
162                 chop( $users );
163                 $users =~ s/,$//;
164                 $aim->send_im($sender, h($users));
165
166         # COMMAND: PEEPS ###############################################################
167         } elsif( $fml_username && $message =~ m/^\s*peeps\s*$/ ) {
168                 $aim->send_im($sender, "Look at you, you have <a href='$site/peeps'>" . ( keys %{$sessions_ref->{$sender}->{"peeps"}} ) . " peeps</a>!" );
169                
170         # COMMAND: VERSION ###############################################################
171         } elsif( $message =~ m/version/ ) {
172                 log_mesg( \*LOG, "version", " $sender" );
173                 $aim->send_im($sender, get_version());
174        
175         # COMMAND: RECENT ###############################################################
176         } elsif( $message =~ m/(links|recent)/ ) {
177                 log_mesg( \*LOG, "recent", " $sender" );
178                 $aim->send_im($sender, "recent links here, soon! (not finished yet, sorry");
179        
180         # COMMAND: LOG ###############################################################
181         } elsif( $message =~ m/(^log)/ ) {
182                 log_mesg( \*LOG, "log test", " $message from $sender" );
183        
184         # COMMAND: HELP ###############################################################
185         } elsif( $message =~ m/help/ || $message =~ m/commands/ || $message =~ m/\?/ || $message =~ m/^\shi\s*$/ || $message =~ m/^\shello\s*$/ || $message =~ m/^\syo\s*$/ ) {
186                 log_mesg( \*LOG, "help", " $sender" );
187
188                 $aim->send_im($sender, "<b>This is the Feed Me Links AIM Bot</b>:
189 From here, you can do most anything you can do on Feed Me Links. It's easy to get started.
190 <b>Paste</b> or <b>type a URL to begin</b>.\nother commands to try: who, peeps, credits, or help" );
191
192         # COMMAND: STATUS ###############################################################
193         } elsif( $message =~ m/status/ ) {
194                 log_mesg( \*LOG, "status", " $sender" );
195                 $aim->send_im($sender, "<b>DEBUG DUMP</b>:\nsender: $sender\nmessage: $message" );
196        
197         # COMMAND: CREDITS ###############################################################
198         } elsif( $message =~ m/credits/ ) {
199                 log_mesg( \*LOG, "credits", " $sender" );
200                         $aim->send_im($sender, h("by <b><a href='http://jm3.net'>John Manoogian III / jm3</a></b>"));
201
202         # COMMAND: RENAME ###############################################################
203         } elsif( $fml_username && $sessions_ref->{$sender}->{"last_link"} && $sessions_ref->{$sender}->{"renamed"} == 0 && $message =~ m/rename(:| )/ ) {
204                         $sessions_ref->{$sender}->{"last_action"} = "rename";
205                         $sessions_ref->{$sender}->{"renamed"}  = 1;
206                         my $link = $sessions_ref->{$sender}{"last_link"}; # convenience var
207                         log_mesg( \*LOG, "rename", " $message from $sender" );
208
209                         my $name = $message;
210                         $name =~ s/^rename(:|\s+)(\s*)?//;
211                         my $pretty_name = $name;
212                         $name = encode( $name );
213
214                         # HACK: not sure why the proxy's credential'ed password isn't being passed in, but passing it on the URL works. whatever.
215                         my $url = "$site/api/rename/" . $sessions_ref->{$sender}{"fml_username"} . "&id=$link&name=$name&password=" . encode($sessions_ref->{$sender}{"fml_password"});
216                         log_mesg( \*LOG, "debug", " $url" );
217                         my $response = $sessions_ref->{$sender}->{"proxy"}->get( $url , []);
218                         my $xp = XML::XPath->new(xml => $response->content);
219                         my $response_code = "" . XML::XPath->new(xml => $response->content)->findnodes('/rest/response/@code');
220                         if( $response_code == "success" ) {
221                                 $aim->send_im($sender, h("Thanks! We renamed <a href='$site/$link'><b>$pretty_name</b></a>."));
222                                 $sessions_ref->{$sender}->{"last_name"} = $pretty_name;
223                                 if( $sessions_ref->{$sender}->{"added_tags"} == 0 ) {
224                                         $aim->send_im($sender, h(get_message( "add_tags")));
225                                 }
226                         } else {
227                                 $aim->send_im($sender, h("<b>Oops, the server screwed something up!</b>\n$response_code" ));
228                         }
229                         log_mesg( \*LOG, "debug", "response: $response_code renaming $link to $message" );
230        
231         # COMMAND: SHARE ###############################################################
232         } elsif( $fml_username && $sessions_ref->{$sender}->{"last_link"} && $message =~ m/\s*share\s*$/ ) {
233
234                         # cache anyone who we CAN share with in the session, first
235                         if( ! $sessions_ref->{ $sender }{ "shareables" } ) {
236                                 my $shareables_ref = ();
237                                 while( my ($peep_fml_username, $peep_aim_name) = each( %{$sessions_ref->{$sender}->{"peeps"}} )) {
238                                         if( $peep_aim_name ) {
239                                                 $shareables_ref->{ $peep_fml_username } = $peep_aim_name;
240                                                 log_mesg( \*LOG, "added $peep_fml_username to sharebles" );
241                                         }
242                                 }
243                                 $sessions_ref->{ $sender }{ "shareables" } = $shareables_ref;
244                         }
245                        
246                         my $shareables_string = get_printable_user_string_from_hash( $sessions_ref->{$sender}->{"shareables"} );
247                         my $online_peeps = who_of_my_peeps_are_online( $sessions_ref, $sender );
248                         my $online_string = get_printable_user_string_from_hash( $online_peeps );
249
250                         $aim->send_im( $sender,
251                                 "<b>Share it, baby!</b>\nOf your <a href='$site/peeps'>"
252                                 . ( keys %{$sessions_ref->{$sender}->{"peeps"}} )
253                                 . " peeps</a>, "
254                                 . ( keys %{$sessions_ref->{$sender}->{"shareables"}} )
255                                 . " (" . $shareables_string . ")"
256                                 . " are using the Feed Me Links bot." );
257                         my $delta_not_using = (keys %{$sessions_ref->{$sender}->{"peeps"}}) - (keys %{$sessions_ref->{ $sender }{ "shareables" }});
258                         if( $delta_not_using ) {
259                                 $aim->send_im( $sender, h( "($delta_not_using of your peeps aren't using the cool Feed Me Links bot yet. "
260                                 . "Want to invite them so you can share and chat? <a href='$site/invite?mode=not_on_aim'><b>Click to invite</b></a>.)" ));
261                         }
262                        
263                         $aim->set_callback_im_ok(\&sent_message);
264                         # FIXME: send to the online-er's here.
265                         log_mesg( \*LOG, "starting loop of send to peeps" );
266                         while( my ($fml_user, $aim_name) = each( %{ $sessions_ref->{$sender}->{"shareables"} })) {
267                         #while( my ($fml_user, $aim_name) = each( %{$online_peeps})) {
268
269                                 my $result_code =
270                                         my $mesg = h("Hi $fml_user, $sender wants to share this with you:\n<a href='" .$sessions_ref->{$sender}{"last_link"} . "'>" . $sessions_ref->{$sender}{"last_name"} . "</a>");
271                                         $aim->send_im( $aim_name, $mesg ); # FIXME need link name
272                                         log_mesg( \*LOG, "sent $mesg to $aim_name" );
273                         }
274
275                         # FIXME: print "sent to : foo, bar, etc
276
277  
278         # COMMAND: TAG ###############################################################
279         } elsif( $fml_username && $sessions_ref->{$sender}{"last_link"} && $sessions_ref->{$sender}->{"added_tags"} == 0 ) {
280                         $sessions_ref->{$sender}->{"last_action"} = "added_tags";
281                         $sessions_ref->{$sender}->{"added_tags"}  = 1;
282                         $aim->send_im($sender, "Mmm, TAGS! Let me add those for you...");
283                         log_mesg( \*LOG, "tagging", " $message from $sender" );
284
285                         my $tags = $message;
286                         $tags =~ s/, /,/g;
287                         $tags = encode( $tags );
288                         # HACK: not sure why the proxy's credential'ed password isn't being passed in, but passing it on the URL works. whatever.
289                         my $url = "$site/api/add_tags/" . $sessions_ref->{$sender}{"fml_username"} . "&id=" . $sessions_ref->{$sender}{"last_link"}
290                                 . "&tags=$tags&password=" . encode($sessions_ref->{$sender}{"fml_password"});
291                         my $response = $sessions_ref->{$sender}->{"proxy"}->get( $url , []);
292                         my $response_code = "" . XML::XPath->new(xml => $response->content)->findnodes('/rest/response/@code'); # HACK: string type coercion
293                         log_mesg( \*LOG, "debug", "response: $response_code adding adding $tags with URL $url" );;
294                         if( $response_code == "success" ) {
295                                 my $tag_noun = "tag";
296                                 if( $tags =~ m/,/ ) {
297                                         $tag_noun .= "s";
298                                 }
299                                 $tag_noun .= " <b>$message</b>";
300                                 $aim->send_im($sender, h("Thanks! We added the tags <b>$message</b> to <a href='$site/" . $sessions_ref->{$sender}->{"last_link"} . "'>your link</a>"));
301                                 if( $sessions_ref->{$sender}->{"renamed"} == 0 ) {
302                                         $aim->send_im($sender, h(get_message( "rename")));
303                                 }
304                         }
305                
306         # COMMAND: SHOW TAG ###############################################################
307         } elsif( $fml_username && $sessions_ref->{$sender}{"tags"}{$message} ) {
308
309                 my $url = "$site/api/tag/" . encode( $sessions_ref->{$sender}{"tags"}{$message} )
310                         . "&user=" . encode( $sessions_ref->{$sender}{"fml_username"} )
311                         . "&password=" . encode($sessions_ref->{$sender}{"fml_password"});
312                 log_mesg( \*LOG, "debug", "found a tag, will get it with url: $url");
313                 my $response = $sessions_ref->{$sender}->{"proxy"}->get( $url , []);
314
315                 my $num_links = "" . XML::XPath->new(xml => $response->content)->findnodes('/posts/@num_links');
316                 log_mesg( \*LOG, "debug", "got num links $num_links");
317                 if( $num_links != 0 )  {
318                         my $link_nodes = XML::XPath->new(xml => $response->content)->findnodes('/posts/post');
319                         my $summary = "";
320                         my $max = $num_recent;
321                         my $c = 0;
322                         foreach my $link_node ($link_nodes->get_nodelist) {
323                                 if( $c < $max ) {
324                                         $summary .=
325                                                 "<a href='"
326                                                         . $link_node->findnodes( "./\@href" )
327                                                         . "'>"
328                                                         . $link_node->findnodes( "./\@description" )
329                                                         . "</a>, ";
330                                 }
331                                 ++ $c;
332                         }
333                         $summary =~ s/, $//;
334
335                         log_mesg( \*LOG, "debug", "summary: $summary" );
336                 $aim->send_im($sender, h("You have <a href='$site/u/" . encode( $sessions_ref->{$sender}{"fml_username"}) . "/tags/" . encode($message)
337                         . "'>$num_links links</a> tagged with <b><font size='6'>$message</font></b>, including $summary" ));
338                 }
339
340         # COMMAND: PEEP ###############################################################
341         } elsif( $fml_username && exists $sessions_ref->{$sender}{"peeps"}{$message} ) {
342                 my $peep = encode( $message );
343                 $aim->send_im($sender, h("<a href='$site/u/$peep'>$peep</a> is your peep! APE CANNOT KILL APE!" ));
344
345                         my $url = "$site/api/recent/$peep";
346                         log_mesg( \*LOG, "debug",