yesssSMS
view release on metacpan or search on metacpan
2023-02-23 Armin Fuerst <armin@fuerst.priv.at>
Release 2.21
Nail to old layout because WebSMS was removed
from the new layout
2020-11-11 Armin Fuerst <armin@fuerst.priv.at>
Release 2.20
Implemented token introduced on website on November 11th, 2020
Added status_line in case of errors when sending message
2019-08-25 Armin Fuerst <armin@fuerst.priv.at>
Release 2.15
Removed accidental remaining debug output
2019-08-25 Armin Fuerst <armin@fuerst.priv.at>
Release 2.14
Adopted due to little changes of the website
2018-09-04 Armin Fuerst <armin@fuerst.priv.at>
Release 2.13
Improved documentation for getSubscriptions().
2018-09-04 Armin Fuerst <armin@fuerst.priv.at>
Release 2.12
Corrected typo in description
2018-08-31 Armin Fuerst <armin@fuerst.priv.at>
Release 2.11
Added Changelog
2018-08-31 Armin Fuerst <armin@fuerst.priv.at>
Release 2.10
Added the possibility to change the sending phonenumber
Login and selecting phonenumber reads details about tarifs and packages
Details about tarif and packages are available through getSubscriptions
2014-08-01 Armin Fuerst <armin@fuerst.priv.at>
Release 2.00
Adopted for the new webinterface
2014-03-14 Armin Fuerst <armin@fuerst.priv.at>
Release 1.00
Initial release - allows to send short messages through
the webinterface of yesss!
Makefile.PL
MANIFEST
README
t/yesssSMS.t
lib/yesssSMS.pm
---
abstract: 'Send text messages to mobile phones through the website of yesss!'
author:
- 'Armin Fuerst <armin@fuerst.priv.at>'
build_requires:
ExtUtils::MakeMaker: 0
configure_requires:
ExtUtils::MakeMaker: 0
distribution_type: module
dynamic_config: 0
generated_by: 'ExtUtils::MakeMaker version 6.57_05'
license: unknown
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
name: yesssSMS
no_index:
directory:
- t
- inc
requires: {}
version: 2.21
Makefile.PL view on Meta::CPAN
use 5.014002;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
NAME => 'yesssSMS',
VERSION_FROM => 'lib/yesssSMS.pm', # finds $VERSION
PREREQ_PM => {
'HTML::Parser' => '3.71',
'LWP::UserAgent' => '6.08',
'HTTP::Cookies' => '6.01',
}, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'lib/yesssSMS.pm', # retrieve abstract from module
AUTHOR => 'Armin Fuerst <armin@fuerst.priv.at>') : ()),
);
yesssSMS version 2.21
=====================
Objects of the yesssSMS class are only able to send text messages to
mobile phones through the website of yesss! (Kontomanager). Kontomanager
might also be in use by other providers (probably Georg, Krone und Kurier, but
this is not tested). Adopting yesssSMS for the use with other providers might
be simple, feel free to contact me if you are willing to try.
To be able to use this service, you need to have an account at yesss!
(a mobile phone). The target phone number must be provided with the
international code starting with 00 (e.g. 0043 for Austria).
INSTALLATION
To install this module type the following:
perl Makefile.PL
make
make install
DEPENDENCIES
This module requires these other modules and libraries:
* strict
* warnings
* HTML::Parser
* LWP::UserAgent
* HTML::Cookies
COPYRIGHT AND LICENCE
Copyright (C) 2014-2023 by Armin Fuerst
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.14.2 or,
at your option, any later version of Perl 5 you may have available.
lib/test.pl view on Meta::CPAN
#!/usr/bin/perl
use strict;
require "./yesssSMS.pm";
my $sms = yesssSMS->new();
$sms->login('06769510102','x16802');
if ($sms->getLastResult!=0)
{
print STDERR "Error during login: ".$sms->getLastError()."\n";
exit;
}
$sms->sendmessage('00436769510102','Testnachricht');
if ($sms->getLastResult!=0)
{
print STDERR "Error during sendmessage: ".$sms->getLastError()."\n";
exit;
}
$sms->logout();
if ($sms->getLastResult!=0)
{
print STDERR "Error during logout: ".$sms->getLastError()."\n";
exit;
}
lib/yesssSMS.pm view on Meta::CPAN
package yesssSMS;
use 5.014002;
use strict;
use warnings;
use HTML::Parser;
use LWP::UserAgent;
use HTTP::Cookies;
require Exporter;
our @ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use yesssSMS ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
);
our $VERSION = '2.21';
sub new
{
my $self = {};
$self->{LOGINSTATE} = 0;
#$self->{URL}="https://www.yesss.at/kontomanager.at/";
$self->{URL}="https://www.kontomanager.at/";
# www.yesss.at
# CookieSettings: %7B%22categories%22%3A%5B%22necessary%22%5D%7D / {"categories":["necessary"]}
# create useragent and cookie jar
$self->{UA} = LWP::UserAgent->new;
$self->{COOKIEJAR} = HTTP::Cookies->new();
$self->{COOKIEJAR}->set_cookie(0, 'CookieSettings', '{"categories":["necessary"]}',
'/', 'www.yesss.at', 443, 0, 0, 86400, 0);
$self->{UA}->cookie_jar($self->{COOKIEJAR});
bless ($self);
return $self;
}
sub login
{
my $self = shift;
my $phoneParser;
($self->{TELNR},
$self->{PASS})=@_;
# don't login if logged in...
if ($self->{LOGINSTATE} == 1)
{
$self->{LASTERROR}='Cannot login when already logged in';
$self->{RETURNCODE}=1;
return 1;
}
# go to start page
$self->{CONTENT}=$self->{UA}->get($self->{URL}."index.php?brand=yesss&callfromapp=1&appversion=2_3");
# if there was an error on the start page, stop
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error loading startpage of YESSS!';
$self->{RETURNCODE}=2;
return 2;
}
# do the login post
$self->{CONTENT}=$self->{UA}->post($self->{URL}."index.php",{'login_rufnummer' => $self->{TELNR},'login_passwort' => $self->{PASS}});
# successful login results in redirect
if (!($self->{CONTENT}->is_redirect))
{
$self->{LASTERROR}='Error sending credentials!';
$self->{RETURNCODE}=3;
return 3;
}
# usually, a redirect is replied
while ($self->{CONTENT}->is_redirect)
{
# follow redirect
$self->{CONTENT}=$self->{UA}->post($self->{CONTENT}->header("Location"),{'login_rufnummer' => $self->{TELNR},'login_passwort' => $self->{PASS}});
# if there was an error during redirect, stop
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error during post-login redirect';
$self->{RETURNCODE}=4;
print $self->{CONTENT}->status_line;
return 4;
}
}
# parse interesting values
$phoneParser=HTML::Parser->new(api_version=>3,
start_h => [\&loginStartTagParse, "self,tagname,attr"],
text_h => [\&loginTextParse, "self, text"],
end_h => [\&loginEndTagParse, "self, tagname"]
);
# bring my "self" into the handlers without global vars
# delete possible existing subscriptions
# initialize some variables needed for the parser
undef($self->{SUBSCRIPTIONS});
$phoneParser->{'yesssSMSself'}=$self;
$phoneParser->{'inSubscriber'}=0;
$phoneParser->{'inProgresslist'}=0;
$phoneParser->{'inProgressheading'}=0;
$phoneParser->{'amountSubscriptions'}=0;
$phoneParser->{'amountItems'}=0;
$phoneParser->parse($self->{CONTENT}->decoded_content);
# print found phone numbers and their values
$self->{LOGINSTATE}=1;
$self->{LASTERROR}='Login successful';
$self->{RETURNCODE}=0;
return 0;
}
sub selectPhonenumber
{
my $self = shift;
my ($telnr)=@_;
my $phoneParser;
# switching is only possible after login
if ($self->{LOGINSTATE} == 0)
{
$self->{LASTERROR}='Not logged in while trying to select phonenumber';
$self->{RETURNCODE}=1;
return 1;
}
# check, if the requested phonenumber is valid
if (! defined($self->{SUBSCRIBERS}->{$telnr}))
{
$self->{LASTERROR}='Requested phonenumber not available in account';
$self->{RETURNCODE}=6;
return 6;
}
$self->{CONTENT}=$self->{UA}->post($self->{URL}."kundendaten.php",
{
'subscriber' => $self->{SUBSCRIBERS}->{$telnr},
'groupaction' => 'change_subscriber'
}
);
# stop on error
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error while selecting phonenumber';
$self->{RETURNCODE}=7;
return 7;
}
# parse interesting values
$phoneParser=HTML::Parser->new(api_version=>3,
start_h => [\&loginStartTagParse, "self,tagname,attr"],
text_h => [\&loginTextParse, "self, text"],
end_h => [\&loginEndTagParse, "self, tagname"]
);
# bring my "self" into the handlers without global vars
undef($self->{SUBSCRIPTIONS});
$phoneParser->{'yesssSMSself'}=$self;
$phoneParser->{'inSubscriber'}=0;
$phoneParser->{'inProgresslist'}=0;
$phoneParser->{'inProgressheading'}=0;
$phoneParser->{'amountSubscriptions'}=0;
$phoneParser->{'amountItems'}=0;
$phoneParser->parse($self->{CONTENT}->decoded_content);
}
sub sendmessage
{
my $self = shift;
my ($telnr,$message)=@_;
my $tokenParser;
# only send message when login was successful
if ($self->{LOGINSTATE} == 0)
{
$self->{LASTERROR}='Not logged in while trying to send a message';
$self->{RETURNCODE}=1;
return 1;
}
if (!($telnr=~/^00/) || (length($telnr)<14))
{
$self->{LASTERROR}='Invalid destination (not starting with 00 or too short)';
$self->{RETURNCODE}=3;
return 3;
}
# go to correct menu item
$self->{CONTENT}=$self->{UA}->post($self->{URL}."websms.php");
# stop on error
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error while selecting SMS menu';
$self->{RETURNCODE}=4;
return 4;
}
# get token for websms.php
$tokenParser=HTML::Parser->new(api_version=>3,
start_h => [\&websmsGetTokenStartTagParse, "self,tagname,attr"],
end_h => [\&websmsGetTokenEndTagParse, "self, tagname"]
);
$self->{'websmsToken'}='';
$tokenParser->{'inWebsmsSendForm'}=0;
$tokenParser->{'yesssSMSself'}=$self;
$tokenParser->parse($self->{CONTENT}->decoded_content);
# try to send message
$self->{CONTENT}=$self->{UA}->post($self->{URL}."websms_send.php",
{ 'to_netz' => 'a',
'to_nummer' => $telnr,
'nachricht' => $message,
'token' => $self->{'websmsToken'}
});
# stop on error
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error while sending message ('.
$self->{CONTENT}->status_line.')';
$self->{RETURNCODE}=5;
return 5;
}
$self->{LASTERROR}='Message sent successfully';
$self->{RETURNCODE}=0;
return 0;
}
sub getLoginstate
{
my $self = shift;
return $self->{LOGINSTATE};
}
sub logout
{
my $self = shift;
# don't logout if not logged in...
if ($self->{LOGINSTATE} == 0)
{
$self->{LASTERROR}='Cannot logout when not logged in.';
$self->{RETURNCODE}=1;
return 1;
}
# post the logout url
$self->{CONTENT}=$self->{UA}->post($self->{URL}."index.php?dologout=1");
# if there was an error during logout, stop
if (!($self->{CONTENT}->is_success))
{
$self->{LASTERROR}='Error during logout.';
$self->{RETURNCODE}=2;
return 2;
}
# reset LOGINSTATE
$self->{LOGINSTATE}=0;
$self->{LASTERROR}='Logout successful';
$self->{RETURNCODE}=0;
return 0;
}
sub getLastResult
{
my $self = shift;
return $self->{RETURNCODE};
}
sub getLastError
{
my $self = shift;
return $self->{LASTERROR};
}
sub getContent
{
my $self = shift;
return $self->{CONTENT};
}
sub getSubscriptions
{
my $self = shift;
return $self->{SUBSCRIPTIONS};
}
sub DESTROY
{
my $self = shift;
if ($self->{LOGINSTATE}==1)
{
$self->logout();
}
}
####### methods for parser
# login/switch phone number
sub loginStartTagParse
{
my ($self, $tagname, $attr) = @_;
if (($self->{'inSubscriber'} != 1) &&
($self->{'inProgresslist'} < 1))
{
if (($tagname eq 'select') &&
($attr->{'id'} eq 'subscriber'))
{
$self->{'inSubscriber'}=1;
}
elsif (($tagname eq 'div') &&
(defined ($attr->{'class'})) &&
($attr->{'class'} eq 'progress-list'))
{
$self->{'inProgresslist'}++;
}
}
elsif ($self->{'inSubscriber'} == 1)
{
if ($tagname eq 'option')
{
$self->{'lastValue'}=$attr->{'value'};
}
}
elsif ($self->{'inProgresslist'} >= 1)
{
if ($tagname eq 'div')
{
if ($attr->{'class'} eq 'info-list-item')
{
$self->{'inProgresslist'}=0;
$self->{'amountItems'}=0;
}
elsif ($attr->{'class'} eq 'progress-item')
{
$self->{'amountItems'}++;
$self->{'inProgresslist'}++;
}
else
{
$self->{'inProgresslist'}++;
}
}
if ($tagname eq 'h3')
{
if ((defined($attr->{'id'})) &&
($attr->{'id'} eq 'kostenkontrolle'))
{
# we ignore 'Kostenkontrolle'
$self->{'inProgresslist'}=0;
$self->{'amountItems'}=0;
}
else
{
$self->{'inProgressheading'}=1;
}
}
}
}
sub loginTextParse
{
my ($self, $text) = @_;
my $phonenumber;
my $progressname;
my $value;
&trim(\$text);
if (($self->{'inSubscriber'} == 1) &&
(length($text)>1))
{
($phonenumber)=$text=~/^([0-9]+)[^0-9]/;
$self->{'yesssSMSself'}->{SUBSCRIBERS}->{$phonenumber}=$self->{'lastValue'};
}
elsif (($self->{'inProgressheading'} == 1) &&
(length($text)>1))
{
($progressname)=$text=~/\s*(.*)\s*:$/;
$self->{'amountSubscriptions'}++;
$self->{'yesssSMSself'}->{SUBSCRIPTIONS}->[$self->{'amountSubscriptions'}-1]->{'name'}=$progressname;
}
elsif (($self->{'inProgresslist'} >= 1) &&
(length($text)>1))
{
if ($text=~/^[0-9]+\s/)
{
($value)=$text=~/^[0-9]+\s(.+)$/;
$self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
[$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'unit'}=$value;
}
elsif ($text=~/^Verbraucht:/)
{
($value)=$text=~/^Verbraucht: ([0-9]+)\s*$/;
$self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
[$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}=$value;
}
elsif ($text=~/^Verbraucht Inland:/)
{
($value)=$text=~/^Verbraucht Inland: ([0-9]+)\s*$/;
$self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
[$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}+=$value;
}
elsif ($text=~/^Verbleibend/)
{
($value)=$text=~/^Verbleibend: ([0-9]+)$/;
$self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
[$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'remaining'}=$value;
}
}
}
sub loginEndTagParse
{
my ($self, $tagname) = @_;
if ($self->{'inSubscriber'} == 1)
{
if ($tagname eq 'select')
{
$self->{'inSubscriber'}=0;
}
}
elsif ($self->{'inProgresslist'} >= 1)
{
if ($tagname eq 'div')
{
$self->{'inProgresslist'}--;
if ($self->{'inProgresslist'} == 0)
{
$self->{'amountItems'}=0;
}
}
if ($self->{'inProgressheading'} == 1)
{
if ($tagname eq 'h3')
{
$self->{'inProgressheading'}=0;
}
}
}
}
## methods for parsing websms_send.php for the token
sub websmsGetTokenStartTagParse
{
my ($self, $tagname, $attr) = @_;
if ($self->{'inWebsmsSendForm'} != 1)
{
if ($tagname eq 'form')
{
if ($attr->{'action'} eq 'websms_send.php')
{
$self->{'inWebsmsSendForm'} = 1,
}
}
}
else
{
if ($tagname eq 'input')
{
if (($attr->{'type'} eq 'hidden') &&
($attr->{'name'} eq 'token'))
{
$self->{'yesssSMSself'}->{'websmsToken'}=$attr->{'value'};
}
}
}
}
sub websmsGetTokenEndTagParse
{
my ($self, $tagname) = @_;
if ($self->{'inWebsmsSendForm'} == 1)
{
if ($tagname eq 'form')
{
$self->{'inWebsmsSendForm'} = 0;
}
}
}
sub trim
{
my $string=$_[0];
$$string =~ s/^\s+//;
$$string =~ s/\s+$//;
}
1;
__END__
# Below is the documentation for the module.
=head1 NAME
yesssSMS - Send text messages to mobile phones through the website of yesss!
=head1 SYNOPSIS
use yesssSMS;
use strict;
# create SMS object
my $sms=yesssSMS->new();
# login to the site with your phone number and the password
$sms->login("06811234567","MyPassword");
# check whether login was successful
if ($sms->getLastResult!=0)
{
print STDERR "Error during login: ".$sms->getLastError()."\n";
}
# if multiple phonenumbers are available, switch if needed
$sms->selectPhonenumber('4368187654321');
# check whether the switch was successfull
if ($sms->getLastResult!=0)
{
print STDERR "Error during selectPhonenumber: ".
$sms->getLastError()."\n";
}
# print remaining units of the main subscription
print "Remaining: ";
print $sms->{SUBSCRIPTIONS}->[0]->{'items'}->[0]->{'remaining'}." ";
print $sms->{SUBSCRIPTIONS}->[0]->{'items'}->[0]->{'unit'}."\n";
# send a text message
$sms->sendmessage('00436817654321','Just testing...');
# check whether the message was delivered
if ($sms->getLastResult!=0)
{
print STDERR "Error during sendmessage: ".
$sms->getLastError()."\n";
}
# logout of site
$sms->logout();
# check whether login was successful
if ($sms->getLastResult!=0)
{
print STDERR "Error during logout: ".$sms->getLastError()."\n";
}
=head1 DESCRIPTION
Objects of the yesssSMS class are only able to send text messages to
mobile phones through the website of yesss! (Kontomanager). Kontomanager
might also be in use by other providers (probably Georg, Krone und Kurier, but
this is not tested). Adopting yesssSMS for the use with other providers might
be simple, feel free to contact me if you are willing to try.
To be able to use this service, you need to have an account at yesss!
(a mobile phone). The target phone number must be provided with the
international code starting with 00 (e.g. 0043 for Austria).
This module requires following modules:
* strict
* warnings
* HTML::Parser
* LWP::UserAgent
* HTTML::Cookies
=head1 METHODS
The following method is used to construct a new yesssSMS object:
=over
=item $sms = yesssSMS->new()
=back
The following method logs into the website with your phone number and the password:
=over
=item $sms->login(MyPhonenumber,Password)
=back
The following method selects the sending phonenumer (for accounts with multiple phones):
=over
=item $sms->selectPhonenumer(MyAlternatePhonenumer)
=back
The following method sends a text message if a login was successful before:
=over
=item $sms->sendmessage(OtherPhonenumer,Textmessage)
It is possible to send multiple text messages during one login.
=back
The following method logs out of the website of yesss!
=over
=item $sms->logout()
=back
The following method returns the hash to all subscription details:
=over
=item $sms->getSubscriptions()
Returns an array with the subscription details:
* each array contains a hash with "type", "name" and "items".
* "name" is the name of the subscription
* "items" contains an array with all items contained in the subscription.
* each item-array contains a hash with "unit", "used" and "remaining"
* "used" is the amount of already used units during the current accounting period
* "remaining" is the amount of already remaining units during the current accounting period
* "unit" contains the unit of "used" and "remaining"
=back
The following method returns the current login state:
=over
=item $sms->getLoginstate()
0 means: not logged in
1 means: logged in
=back
The following method returns the result of the last operation:
=over
=item $sms->getLastResult()
0 means: successful
>0 means: an error occured
=back
The following method returns a textual description of the result of the
last operation:
=over
=item $sms->getLastError()
=back
The following method returns the LWP::UserAgent last return content:
=over
=item $sms->getContent()
=back
=head1 HISTORY
=over 8
=item 1.00
Original version
=item 2.00
Adopted for the new website being online since August 1st, 2014
=item 2.10
Added the possibility to change the sending phonenumber
Login and selecting phonenumber reads details about tarifs and packages
Details about tarif and packages are available through getSubscriptions
=item 2.11
Added "Changes"
=item 2.12
Corrected typo in description
=item 2.13
Improved documentation for getSubscriptions().
=item 2.14
Little adoptions due to changes in the website
Removed 'type' from subscriptions as they were removed from the site.
=item 2.15
Removed accidental remaining debug output
=item 2.20
Implemented token introduced on website on November 11th, 2020
Added status_line in case of errors when sending message
=item 2.21
Nailed to old interface because websms was removed from the new UI
=back
=head1 AUTHOR
Armin Fuerst
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2014 by Armin Fuerst
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.14.2 or,
at your option, any later version of Perl 5 you may have available.
=cut
t/yesssSMS.t view on Meta::CPAN
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl yesssSMS.t'
#########################
# change 'tests => 1' to 'tests => last_test_to_print';
use strict;
use warnings;
use Test::More tests => 1;
BEGIN { use_ok('yesssSMS') };
#########################
# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.
( run in 0.442 second using v1.01-cache-2.11-cpan-397a349f891 )