[Perl] VodaSMS - Utility foga per l'invio automatico di SMS dal sito della Vodafone

Stato
Discussione chiusa ad ulteriori risposte.

imported_BlackLight

Utente Silver
16 Agosto 2007
211
8
1
98
La possibilità per gli utenti Vodafone di inviare fino a 10 sms gratis al giorno da vodafone.it verso altri utenti Vodafone è una cosa foga. Dover aprire il browser ogni volta, mandarlo sul sito, loggarsi, aprire 4 pagine non proprio leggere nel mezzo, e fare questa trafila ogni volta che si vuole inviare un sms, è una cosa un po' meno foga. La buona notizia è che la Vodafone ha sviluppato il Vodafone Widget, che consente di automatizzare questa procedura. La cattiva notizia è che questo Widget è solo per piattaforme Windows, anzi usando Firefox a quanto pare non si riesce manco a scaricarlo dalla pagina in Flash. Quindi, assodato che le cose fatte in casa sono le migliori, ho fatto uno script in Perl tanto carino che consente di inviare sms attraverso il sito della Vodafone usando la riga di comando. L'uso è estremamente semplice:

Codice:
vodasms -u <username su vodafone.it> -p <password su vodafone.it> -n <numero a cui inviare l'sms>

L'sms da inviare si può specificare in diversi modi:

- Da riga di comando, opzione -m (es. '-m "Questa e' una prova"').
- Via stdin (se non si specifica l'opzione -m, si può inserire tranquillamente l'sms via standard input, digitando <ENTER><CTRL+D> per indicare la fine).
- Da un file di testo esterno, con la redirezione (es. '< sms.txt').

La cosa bella dell'invio da terminale è che si può creare una rubrica telefonica in modo estremamente figo. Se invio spesso sms a Pippo, e il suo numero di cellulare è 123456, posso semplicemente piazzare in .bashrc, .zshrc, o quel che sia il file di conf della shell che uso, un export PIPPO=123456, quindi inviargli un sms semplicemente dando vodasms -u <utente> -p <password> -n $PIPPO.

È possibile anche stabilire che viewer esterno usare, indispensabile per la visualizzazione del captcha (prima o poi lavorerò su una rete neurale per la risoluzione automatica). Di default uso feh. Se non l'avete installato o non vi piace, potete specificare un altro viewer semplicemente usando l'opzione -v.

Codice:
#!/usr/bin/perl
#===============================================================================
#
#         FILE:  vodasms.pl
#
#        USAGE:  perl vodasms.pl -u <username> -p <password> -n <number>
#        		 [-s <sms message>] [-v <image viewer for the captcha code>
#        		 (default: feh)] [-c <cookie jar file> (default:
#        		 /tmp/vodafone_cookies.txt)]
#
#        		 You can specify the text of your sms in 3 ways:
#        		 - As parameter, i.e. -m "This is my sms"
#        		 - From stdin (just enter your message after starting the
#        		   script without the -m option, and when finished type
#        		   <ENTER><CTRL+D>)
#        		 - From a text file, i.e. vodasms.pl ... < sms.txt
#
#  DESCRIPTION:  A simple and stupid Perl script to automate the sending of
#  	             short text messages to mobile phones from www.vodafone.it
#  	             (of course, you first must have an account on it in order to
#  	             send messages, you can only send messages to mobile phones
#  	             having Vodafone as operator, and you can send at most 10
#  	             messages per day)
#
#      OPTIONS:  ---
# REQUIREMENTS:  ---
#         BUGS:  If a such short script had bugs, I'd better change my job.
#                Anyway, it won't work, of course, when there are some
#                maintenance works on the website (but this is obvious).
#        NOTES:  ---
#       AUTHOR:  BlackLight (http://0x00.ath.cx), [email protected]
#      COMPANY:  LULZ
#      VERSION:  0.1
#      CREATED:  22/02/2010 16:13:57
#     REVISION:  ---
#      LICENCE:  GNU GPL v.3
#===============================================================================

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Cookies;
use HTTP::Request::Common;
use Getopt::Long;

my $user = '';
my $pass = '';
my $sms  = '';
my $num  = '';
my $viewer = '';
my $cookie_jar = '';
my $agent = 'Mozilla/5.0 (BlackLight Vodafone SMS sender)';

sub urlencode  {
	my $str = shift;
	$str =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
	return $str;
}

GetOptions(
	'user=s' => \$user,
	'pass=s' => \$pass,
	'num=s'  => \$num,
	'sms=s'  => \$sms,
	'viewer=s' => \$viewer,
	'cookie_jar=s' => \$cookie_jar,
);

die "Usage: $0 -u <username> -p <password> -n <number> [-s <sms message>]\n".
	"\t[-v <image viewer for the captcha code> (default: feh)] [-c <cookie jar file> (default: /tmp/vodafone_cookies.txt)]\n" if ($user eq '' || $pass eq '' || $num eq '');
die "You did not choose a valid phone number\n" unless ($num =~ /^[0-9]+$/);

$viewer = 'feh' if ($viewer eq '');
$cookie_jar = '/tmp/vodafone_cookies.txt' if ($cookie_jar eq '');

if ($sms eq '')  {
	print "Type your SMS message here (end with <ENTER><CTRL+D>) - MAX: 360 characters\n";
	$sms .= $_ while (<STDIN>);
	print "\n";
}

die "Your message is longer than 360 characters - This is not good, and vodafone.it won't accept it\n" if (length($sms) > 360);

if (length($sms) > 160)  {
	my $answer = '';

	do  {
		print "Warning: your SMS is longer than 160 characters - This means it will be splitted in more messages.\n".
			"Are you going to send it anyway? (y/n) ";

		$answer = <STDIN>;
		chomp($answer);
	} while ($answer !~ /^(y|n)/i);

	die "Ok, as you like dude ^^\n" if ($answer =~ /^n/i);
}

print "Logging in, please wait...\n";

my $lwp  = new LWP::UserAgent;
$lwp->agent($agent);
$lwp->cookie_jar(new HTTP::Cookies(
	file => $cookie_jar,
	autosave => 1
));

my $res = $lwp->request(
	POST 'http://www.vodafone.it/190/trilogy/jsp/login.do', [
		username => $user,
		password => $pass,
]);

while ($res->is_redirect)  {
	$res = $lwp->request(GET $res->header('location'));
}

die "Oh no! There was an error while trying to send your SMS :(\n" unless ($res->is_success);
die "Login failed - Check your username and/or password\n" unless ($res->as_string =~ /logout/i);
print "Login OK\n";

$lwp->request(GET 'http://www.vodafone.it/190/trilogy/jsp/dispatcher.do?ty_key=fdt_invia_sms&tk=9616,2');
$res = $lwp->request(GET 'http://www.areaprivati.vodafone.it/190/trilogy/jsp/dispatcher.do?ty_key=fsms_hp&ipage=next');

while ($res->is_redirect)  {
	$res = $lwp->request(GET $res->header('location'));
}

die "Oh no! There was an error while trying to send your SMS :(\n" unless ($res->is_success);

$res = $lwp->request(
	POST 'http://www.areaprivati.vodafone.it/190/fsms/prepare.do', [
		pageTypeId => '9604',
		programId  => '10384',
		chanelId => '-18126',
		receiverNumber => $num,
		message => $sms,
]);

while ($res->is_redirect)  {
	$res = $lwp->request(GET $res->header('location'));
}

die "Oh no! There was an error while trying to send your SMS :(\n" unless ($res->is_success);
$res = $lwp->request(GET 'http://www.areaprivati.vodafone.it/190/fsms/generateimg.do');

my $begin_data = 0;
open OUT, '> /tmp/vodafone_captcha.jpg';

for (split //, $res->as_string)  {
	$begin_data = 1 if (ord($_) == 0xFF && !$begin_data);
	print OUT $_ if ($begin_data);
}

close OUT;

print "Just insert the value you see, exit the viewer, and press ENTER: ";
`$viewer /tmp/vodafone_captcha.jpg &`;
my $captcha = <STDIN>;
chomp($captcha);
unlink '/tmp/vodafone_captcha.jpg';
print "Performing the request (this may take a while...)\n";

$res = $lwp->request(
	POST 'http://www.areaprivati.vodafone.it/190/fsms/send.do', [
		receiverNumber => $num,
		message => $sms,
		verifyCode => $captcha,
]);

die "You already sent 10 SMS today dude\n" if ($res->as_string =~ /superato/i);
die "For any fucking reason, I was not able to perform your request, sorry :(\n" unless ($res->as_string =~ /correttamente/i);
print "Your SMS was sent ^^\n";

Link:
http://0x00.ath.cx/#nopaste&id=1267015362&lang=perl
 
Codice:
sub urlencode  {
    my $str = shift;
    $str =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
    return $str;
}
Risparmieresti righe di code con URI::Escape e la funzione del modulo uri_escape :p
Comunque bello bello, dopo mi ci metto anche io :D
(io pero' mi sto complicando la vita con i socket)
 
Stato
Discussione chiusa ad ulteriori risposte.