1#!/usr/bin/perl -w
2######################################################################
3# comment_myspace
4# Sccsid:  %Z%  %M%  %I%  Delta: %G%
5# $Id: comment_myspace,v 1.3 2006/03/15 01:49:48 grant Exp $
6######################################################################
7# Copyright (c) 2005 Grant Grueninger, Commercial Systems Corp.
8#
9
10=head1 NAME
11
12comment_myspace - Leave a comment for your Myspace friends
13
14=head1 VERSION
15
16Version 0.03
17
18=cut
19
20our $VERSION = '0.03';
21
22=head1 SYNOPSIS
23
24 usage: comment_myspace ( -m message | -f filename ) [-y] [-d] [-i] [-r]
25     [-n max_count] [-u username -p password] [-c cache_file]
26     [friendID ...]
27
28Simple script to leave a comment for each of our friends using the
29WWW::Myspace::Comment Perl module.  By default, it will leave a maximum
30of 50 comments (see the -n option below), then exit displaying
31a message containing the result code returned from the post_comments
32method (DONE, COUNTER, or CAPTCHA). "perldoc WWW::Myspace::Comment" for
33more info.
34
35=over
36
37=item -m message
38
39Post "message" to the friends' page (beware shell escapes!)
40
41=item -f filename
42
43Read the account, password, and message from filename. The file
44must contain the username on the first line, the password on the
45second line, and the message starting on the third line, like this:
46
47	joe@somewhere.com
48	ILike2havelongpasswords
49	Just stopping by to say hi!
50
51	- Joe
52
53The above will set username to "joe@somewhere.com", the password
54to "ILike2havelongpasswords", and the message to:
55
56  Just stopping by to say hi!
57
58  - Joe
59
60All characters are safe when passing comments this way, and you
61can also pass HTML in the message. Note that myspace does allow users
62to strip HTML from comments, so make sure your stripped message
63is still readable.
64
65=item -y
66
67Yes mode: Don't ask for confirmation, just do it. (careful!!!)
68This is for cron jobs, but normally you should use the confirmation
69to make sure the shell hasn't munged your message and that the friend
70count and exclusion count look ok before you go send stuff you didn't
71want to people you didn't want to...
72
73=item -d
74
75Inserts a random delay before running. Do this is you're running the
76script from crontab to make it look more like a human.
77
78=item -i
79
80Ignore Duplicates.  If the -i flag is passed, comment_myspace will not
81check the profile page for duplciate comments, it will just post.
82
83=item -r
84
85Reset the exclusions file.  comment_myspace remembers who it has commented
86before and won't comment them again.  Using the -r flag resets this list
87(maybe I should call it -f for "forget?" :)
88Use this if you want to post a new comment to people and you don't
89care if you've commented them before. Note that unless you
90use the -i flag also, comment_myspace will still skip profiles on which
91it sees your profile link already.
92
93The reset is done -before- commenting begins.
94
95=item -n max_count
96
97Only post max_count comments.  This defaults to 50 in
98WWW::Myspace::Comment as of this writing.  Setting a value here will
99pass it to the WWW::Myspace::Comment object. This is mostly useful
100for posting fewer than 50 comments at a time, since Myspace
101won't let you post more than that without giving you a CAPTCHA.
102
103=item -u username
104
105Use "username" as the username when logging in
106
107=item -p password
108
109Use this password to log in (must be provided if -u is used
110
111=item friendID
112
113Post to this (or these) friendIDs only
114
115=item -c cache_file
116
117Use "cache_file" as the file to store/read the list of friends
118we've commented. As comments are left, the status of the post will
119be written to this file. If you don't provide this,
120the default cache_file will be used. See WWW::Myspace::Comment
121for details.
122
123=back
124
125=head1 Examples
126
127  Post to only two friends (will prompt for username
128  and password):
129  comment -m 'Merry Christmas\!\!\!' 370234 275034
130
131  Post "Happy New Year!!!" to all our friends (will prompt for username
132  and password):
133  comment -m 'Happy New Year\!\!\!'
134
135  Post to all Joe's friends using "joe@somewhere.com"'s account:
136  comment -m 'Just saying hi' -u joe@somewhere.com -p FooBar92
137
138=head1 Known Issues / To Do
139
140CAPTCHA: MySpace.com allows 53 or 55 posts before requiring a CATCHA
141response, then allows 3 before requiring it agian. Not sure what the
142timeout is on this (12 hours?).
143
144Note that the evolving point of leaving comments is to make sure that
145we're linked to from as many pages as possible, and mentioned on as
146many pages as possible. We want to appear to "be everywhere". Since we
147can only post to about 50 pages a day, we maximize our exposure by
148checking each page we're going to post on to see if we're already there
149and skipping it if we are.
150
151To Do:
152
153  - Provide a CGI interface so band members can coordinate and type in the
154    CAPTCHA code. Interface would act as a relay: for each person we'd
155    auto-post to, display the filled in comment form and have them customize
156    it and/or fill in the captcha code. Could run in semi-automatic mode
157    where it'd only display the page for them if it got a code request.
158
159=cut
160
161#
162######################################################################
163# Setup
164
165# Debugging?
166$DEBUG=0;
167
168######################################################################
169# Libraries we use
170
171($DEBUG) && print "Getting Libraries...\n";
172use WWW::Myspace;
173use WWW::Myspace::Comment;
174
175######################################################################
176# Main Program
177
178# Get passed arguments
179my %args = &parse_args(@ARGV);
180
181# Wait?
182if ( defined $args{'delay'} ) {
183	# Randomly delay up to 1 hour
184	sleep 60 * int( rand( 60 ) )
185}
186
187# Log in, let "WWW::Myspace" prompt for username and password
188print "Logging in to myspace...\n";
189my $myspace = "";
190if ( $args{"username"} ) {
191	$myspace = WWW::Myspace->new( $args{"username"}, $args{"password"} );
192} else {
193	$myspace = new WWW::Myspace;
194}
195die "Login failed\n" unless ( $myspace->logged_in );
196
197# Get list of friends (comment would do the get_friends thing for us,
198# but we'll do it here so we can display more complete info to the user).
199print "Logged in. Getting friends...\n";
200if ( $args{'friend_ids'} ) {
201	@friend_ids = @{$args{'friend_ids'}};
202} else {
203	@friend_ids = $myspace->get_friends;
204}
205
206# Get our Comment object
207my $comment = WWW::Myspace::Comment->new( $myspace );
208
209# Set max_count if we need to
210if ( $args{'max_count'} ) {
211	$comment->max_count( $args{'max_count'} )
212}
213
214# Set ignore_exclusinos if we need to
215if ( defined $args{'ignore_duplicates'} ) {
216	$comment->ignore_duplicates(1);
217}
218
219# Set bypass
220if ( defined $args{'bypass'} ) {
221	$comment->{send_message_on_captcha} = 1;
222}
223
224# Set the exclusions file if they gave us one.
225$comment->cache_file( $args{'cache_file'} ) if ( defined $args{'cache_file'} );
226
227# Reset exclusions file if we need to
228if ( defined $args{'reset_exclusions'} ) {
229	$comment->reset_exlucions('all')
230}
231
232# Get the list of exclusions (we just want the count, really, but
233# this does it.
234@exclusions = $comment->exclusions;
235
236# Tell them what we're going to do
237print "Sending the following comment to ". @friend_ids ." friends,\n".
238	"excluding " . @exclusions . " friends:\n\n" .
239	$args{'message'} . "\n\n";
240
241# Unless they said to just go ahead (i.e. when running from cron),
242# confirm first.
243unless ( $args{'silent'} ) {
244
245	print "Ok (y/n)? ";
246	my $ans=<STDIN>;
247	unless ( $ans =~ /y/i ) { exit 1; }
248
249}
250
251# Comment them
252$comment->noisy(1);
253my $result = $comment->post_comments( $args{'message'}, @friend_ids );
254
255print "Done. Stopped due to $result\n";
256
257#----------------------------------------------------------------------
258# parse_args( @ARGS )
259# Parse command-line arguments and return a has of values
260
261sub parse_args {
262
263	my ( @passed_args ) = @_;
264
265	# Initialize
266	my %args = ();
267	my @friend_ids = ();
268
269	while ( $arg = shift( @passed_args ) ) {
270		if ( $arg eq "-m" ) {
271			$args{'message'} = shift( @passed_args )
272		} elsif ( $arg eq "-y" ) {
273			$args{'silent'}=1;
274		} elsif ( $arg eq "-d" ) {
275			$args{'delay'}=1;
276		} elsif ( $arg eq "-u" ) {
277			$args{'username'}=shift( @passed_args );
278		} elsif ( $arg eq "-p" ) {
279			$args{'password'}=shift( @passed_args );
280		} elsif ( $arg eq "-f" ) {
281			$args{'filename'}=shift( @passed_args );
282		} elsif ( $arg eq "-c" ) {
283			$args{'cache_file'}=shift( @passed_args );
284		} elsif ( $arg eq "-n" ) {
285			$args{'max_count'}=shift( @passed_args );
286		} elsif ( $arg eq "-i" ) {
287			$args{'ignore_duplicates'}=1;
288		} elsif ( $arg eq "-r" ) {
289			$args{'reset_exclusions'}=1;
290		} elsif ( $arg eq "-b" ) {
291			$args{'bypass'}=1;
292		} elsif ( $arg =~ /^[0-9]+$/ ) {
293			push ( @friend_ids, $arg );
294		} else {
295			print "Invalid argument: $arg\n";
296			&fail()
297		}
298
299	}
300
301	# Add friends if we got them
302	if ( @friend_ids ) {
303		$args{'friend_ids'} = \@friend_ids;
304	}
305
306	# Verify data
307	if ( ( $args{'username'} ) && ( ! $args{'password'} ) ) {
308		print "You must specify a password if you provide a username\n";
309		&fail();
310	}
311
312	# Check for -f flag - means we read username, password, and message
313	# from a file
314	if ( defined $args{'filename'} ) {
315		open FILE, "<$args{'filename'}" or die "Invalid filename: $args{'filename'}";
316
317		$args{'username'} = <FILE>;
318		$args{'password'} = <FILE>;
319		undef $args{'message'}; # Just in case...
320		foreach $line ( <FILE> ) {
321			$args{'message'} .= $line;
322		}
323
324		close FILE;
325	}
326
327	# Check the comment
328	unless ( $args{'message'} ) {
329		print "Must provide a message to post using the -m flag\n";
330		&fail();
331	}
332
333	# Debugging output
334	if ( $DEBUG ) {
335		print "Got arguments:\n";
336		foreach $arg (sort( keys( %args ) ) ) {
337			print "$arg:" . $args{"$arg"} . "\n";
338		}
339	}
340
341	# Return our arguments
342	return %args;
343}
344
345#----------------------------------------------------------------------
346# fail()
347# Print usage and exit
348
349sub fail {
350
351	print <<EOT;
352 usage: comment_myspace ( -m message | -f filename ) [-y] [-d] [-i]
353     [-n max_count] [-u username -p password] [-c cache_file]
354     [friendID ...]
355EOT
356	exit 1;
357
358}