| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # -*- perl -*- | 
| 2 |  |  |  |  |  |  | ##---------------------------------------------------------------------------- | 
| 3 |  |  |  |  |  |  | ## Telegram API - ~/lib/Net/API/Telegram/Generic.pm | 
| 4 |  |  |  |  |  |  | ## Version 0.1 | 
| 5 |  |  |  |  |  |  | ## Copyright(c) 2019 Jacques Deguest | 
| 6 |  |  |  |  |  |  | ## Author: Jacques Deguest <jack@deguest.jp> | 
| 7 |  |  |  |  |  |  | ## Created 2019/06/02 | 
| 8 |  |  |  |  |  |  | ## Modified 2019/06/02 | 
| 9 |  |  |  |  |  |  | ## All rights reserved | 
| 10 |  |  |  |  |  |  | ## | 
| 11 |  |  |  |  |  |  | ## This program is free software; you can redistribute  it  and/or  modify  it | 
| 12 |  |  |  |  |  |  | ## under the same terms as Perl itself. | 
| 13 |  |  |  |  |  |  | ##---------------------------------------------------------------------------- | 
| 14 |  |  |  |  |  |  | package Net::API::Telegram::Generic; | 
| 15 |  |  |  |  |  |  | BEGIN | 
| 16 |  |  |  |  |  |  | { | 
| 17 | 1 |  |  | 1 |  | 645 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 18 | 1 |  |  | 1 |  | 16 | use parent qw( Module::Generic ); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 7 |  | 
| 19 | 1 |  |  | 1 |  | 77 | use Devel::StackTrace; | 
|  | 1 |  |  |  |  | 11 |  | 
|  | 1 |  |  |  |  | 43 |  | 
| 20 | 1 |  |  | 1 |  | 8 | use Data::Dumper; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 69 |  | 
| 21 | 1 |  |  | 1 |  | 8 | use Scalar::Util; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 50 |  | 
| 22 | 1 |  |  | 1 |  | 9 | use DateTime; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 24 |  | 
| 23 | 1 |  |  | 1 |  | 15 | use DateTime::TimeZone; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 29 |  | 
| 24 | 1 |  |  | 1 |  | 5 | use File::Temp; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 91 |  | 
| 25 | 1 |  |  | 1 |  | 7 | use File::Spec; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 26 |  |  |  |  |  |  | ## For the JSON::true and JSON::false | 
| 27 | 1 |  |  | 1 |  | 6 | use JSON; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 28 | 1 |  |  | 1 |  | 171 | use TryCatch; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 11 |  | 
| 29 | 1 |  |  | 1 |  | 1064 | use Net::API::Telegram::Number; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 30 | 1 |  |  | 1 |  | 2024 | our( $VERSION ) = '0.1'; | 
| 31 |  |  |  |  |  |  | }; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | sub init | 
| 34 |  |  |  |  |  |  | { | 
| 35 | 0 |  |  | 0 | 1 |  | my $self = shift( @_ ); | 
| 36 |  |  |  |  |  |  | ## Get the init params always present and including keys like _parent and _field | 
| 37 | 0 |  |  |  |  |  | my $init = shift( @_ ); | 
| 38 | 0 |  |  |  |  |  | my $class = ref( $self ); | 
| 39 | 0 | 0 |  |  |  |  | if( Scalar::Util::blessed( $init ) ) | 
| 40 |  |  |  |  |  |  | { | 
| 41 | 0 | 0 |  |  |  |  | if( $init->isa( 'Net::API::Telegram' ) ) | 
| 42 |  |  |  |  |  |  | { | 
| 43 | 0 |  |  |  |  |  | $self->{ '_parent' } = $init; | 
| 44 | 0 |  |  |  |  |  | $self->{ '_debug' } = $init->debug; | 
| 45 |  |  |  |  |  |  | } | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | else | 
| 48 |  |  |  |  |  |  | { | 
| 49 | 0 |  | 0 |  |  |  | $self->{_parent} = $init->{ '_parent' } || warn( "Property '_parent' is not provided in the init hash!\n" ); | 
| 50 | 0 |  | 0 |  |  |  | $self->{_field} = $init->{ '_field' } || warn( "Property '_field' is not provided in the init hash!\n" ); | 
| 51 | 0 |  |  |  |  |  | $self->{debug} = $init->{ '_debug' }; | 
| 52 |  |  |  |  |  |  | } | 
| 53 | 0 |  |  |  |  |  | $self->{_init_strict_use_sub} = 1; | 
| 54 | 0 |  |  |  |  |  | $self->SUPER::init( @_ ); | 
| 55 | 0 |  |  |  |  |  | return( $self ); | 
| 56 |  |  |  |  |  |  | } | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | sub as_hash | 
| 59 |  |  |  |  |  |  | { | 
| 60 | 0 |  |  | 0 | 0 |  | my $self = shift( @_ ); | 
| 61 | 0 |  | 0 |  |  |  | my $class = ref( $self ) || return( $self->error( "This method \"as_hash\" must be called with an object, not using class \"$self\"." ) ); | 
| 62 | 0 |  | 0 |  |  |  | my $anti_loop = shift( @_ ) || '_as_hash_anti_loop_' . time(); | 
| 63 | 0 |  |  |  |  |  | my $hash = {}; | 
| 64 |  |  |  |  |  |  | local $crawl = sub | 
| 65 |  |  |  |  |  |  | { | 
| 66 | 0 |  |  | 0 |  |  | my $this = shift( @_ ); | 
| 67 | 0 | 0 |  |  |  |  | if( Scalar::Util::blessed( $this ) ) | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | { | 
| 69 |  |  |  |  |  |  | ## $self->_message( 3, "\tvalue to check '$this' is an object of type '", ref( $this ), "'." ); | 
| 70 |  |  |  |  |  |  | #my $ref = $self->{ $k }->as_hash( $anti_loop ); | 
| 71 |  |  |  |  |  |  | #return( $ref ); | 
| 72 | 0 | 0 |  |  |  |  | if( $this->can( 'as_hash' ) ) | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | { | 
| 74 |  |  |  |  |  |  | ## $self->_message( 3, "\t\tobject can 'as_hash'" ); | 
| 75 | 0 |  |  |  |  |  | my $h = $this->as_hash( $anti_loop ); | 
| 76 |  |  |  |  |  |  | ## $self->_message( 3, "\t\tobject '", ref( $this ), "' returned value is: ", sub{ $self->dumper( $h ) } ); | 
| 77 | 0 | 0 |  |  |  |  | return( $h ) if( length( $h ) ); | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  | elsif( overload::Overloaded( $this ) ) | 
| 80 |  |  |  |  |  |  | { | 
| 81 | 0 |  |  |  |  |  | return( "$o" ); | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  | elsif( $this->can( 'as_string' ) ) | 
| 84 |  |  |  |  |  |  | { | 
| 85 | 0 |  |  |  |  |  | return( $this->as_string ); | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  | else | 
| 88 |  |  |  |  |  |  | { | 
| 89 | 0 |  |  |  |  |  | warn( "Warning only: I have an object of class \"", ref( $this ), "\" ($this), but is not overloaded and does not have an as_string method, so I don't know what to do to get a string version of it.\n" ); | 
| 90 |  |  |  |  |  |  | } | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  | elsif( ref( $this ) eq 'ARRAY' ) | 
| 93 |  |  |  |  |  |  | { | 
| 94 |  |  |  |  |  |  | ## $self->_message( 3, "\tvalue to check '$this' is an array reference." ); | 
| 95 | 0 |  |  |  |  |  | my $arr = []; | 
| 96 | 0 |  |  |  |  |  | foreach my $that ( @$this ) | 
| 97 |  |  |  |  |  |  | { | 
| 98 | 0 |  |  |  |  |  | my $v = $crawl->( $that ); | 
| 99 |  |  |  |  |  |  | ## $self->_message( 3, "\t\tReturned value to add to array is '$v': ", sub{ $self->dumper( $v ) } ); | 
| 100 | 0 | 0 |  |  |  |  | push( @$arr, $v ) if( length( $v ) ); | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  | ## $self->_messagef( 3, "\treturning %d items in this array.", scalar( @$arr ) ); | 
| 103 | 0 |  |  |  |  |  | return( $arr ); | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  | elsif( ref( $this ) eq 'HASH' ) | 
| 106 |  |  |  |  |  |  | { | 
| 107 |  |  |  |  |  |  | ## $self->_message( 3, "\tvalue to check '$this' is a hash reference." ); | 
| 108 | 0 | 0 |  |  |  |  | return( $this ) if( exists( $this->{ $anti_loop } ) ); | 
| 109 | 0 |  |  |  |  |  | $this->{ $anti_loop }++; | 
| 110 | 0 |  |  |  |  |  | my $ref = {}; | 
| 111 | 0 |  |  |  |  |  | foreach my $k ( keys( %$this ) ) | 
| 112 |  |  |  |  |  |  | { | 
| 113 | 0 |  |  |  |  |  | $ref->{ $k } = $crawl->( $this->{ $k } ); | 
| 114 |  |  |  |  |  |  | } | 
| 115 | 0 |  |  |  |  |  | return( $ref ); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  | else | 
| 118 |  |  |  |  |  |  | { | 
| 119 |  |  |  |  |  |  | ## $self->_message( 3, "\tvalue to check '$this' is a scalar, returning it." ); | 
| 120 | 0 |  |  |  |  |  | return( $this ); | 
| 121 |  |  |  |  |  |  | } | 
| 122 | 0 |  |  |  |  |  | }; | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 0 |  |  |  |  |  | foreach my $k ( keys( %$self ) ) | 
| 125 |  |  |  |  |  |  | { | 
| 126 | 0 | 0 |  |  |  |  | last if( exists( $self->{ $anti_loop } ) ); | 
| 127 |  |  |  |  |  |  | ## Only process keys if their corresponding method exists in their package | 
| 128 | 0 | 0 |  |  |  |  | if( defined( &{ "${class}::${k}" } ) ) | 
|  | 0 |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | { | 
| 130 |  |  |  |  |  |  | ## $self->_message( 3, "Getting data for $k" ); | 
| 131 | 0 | 0 |  |  |  |  | if( $self->_is_boolean( $k ) ) | 
| 132 |  |  |  |  |  |  | { | 
| 133 | 0 | 0 |  |  |  |  | $hash->{ $k } = ( $self->{ $k } ? JSON::true : JSON::false ); | 
| 134 |  |  |  |  |  |  | ## $self->_message( 3, "\tvalue set to boolean '$hash->{$k}'" ); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  | else | 
| 137 |  |  |  |  |  |  | { | 
| 138 | 0 |  |  |  |  |  | $hash->{ $k } = $crawl->( $self->{ $k } ); | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  | } | 
| 142 | 0 |  |  |  |  |  | return( $hash ); | 
| 143 |  |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | sub dumpto | 
| 146 |  |  |  |  |  |  | { | 
| 147 | 0 |  |  | 0 | 0 |  | my $self  = shift( @_ ); | 
| 148 | 0 |  |  |  |  |  | my( $data, $file ) = @_; | 
| 149 | 0 |  |  |  |  |  | local $Data::Dumper::Sortkeys = 1; | 
| 150 | 0 |  |  |  |  |  | local $Data::Dumper::Terse = 1; | 
| 151 | 0 |  |  |  |  |  | local $Data::Dumper::Indent = 1; | 
| 152 | 0 |  |  |  |  |  | local $Data::Dumper::Useqq = 1; | 
| 153 | 0 |  | 0 |  |  |  | my $fh = IO::File->new( ">$file" ) || die( "Unable to create file '$file': $!\n" ); | 
| 154 | 0 |  |  |  |  |  | $fh->print( Data::Dumper::Dumper( $data ), "\n" ); | 
| 155 | 0 |  |  |  |  |  | $fh->close; | 
| 156 |  |  |  |  |  |  | ## 606 so it can work under command line and web alike | 
| 157 | 0 |  |  |  |  |  | chmod( 0666, $file ); | 
| 158 | 0 |  |  |  |  |  | return( 1 ); | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 0 |  |  | 0 | 0 |  | sub parent { return( shift->{_parent} ); } | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | sub TO_JSON | 
| 164 |  |  |  |  |  |  | { | 
| 165 | 0 |  |  | 0 | 0 |  | my $self = shift( @_ ); | 
| 166 | 0 | 0 |  |  |  |  | return( $self->can( 'as_string' ) ? $self->as_string : $self ); | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | sub _download | 
| 170 |  |  |  |  |  |  | { | 
| 171 | 0 |  |  | 0 |  |  | my $self = shift( @_ ); | 
| 172 | 0 |  | 0 |  |  |  | my $id = shift( @_ ) || return( $self->error( "No file id was provided" ) ); | 
| 173 | 0 |  |  |  |  |  | my $opts = {}; | 
| 174 | 0 | 0 |  |  |  |  | $opts = shift( @_ ) if( ref( $_[0] ) eq 'HASH' ); | 
| 175 | 0 |  |  |  |  |  | my $parent = $self->_parent; | 
| 176 |  |  |  |  |  |  | ## https://core.telegram.org/bots/api#getfile | 
| 177 | 0 |  | 0 |  |  |  | my $file = $self->_parent->getFile({ | 
| 178 |  |  |  |  |  |  | 'file_id' => $id | 
| 179 |  |  |  |  |  |  | }) || return( $self->error( "Unable to get file information object for file id $id: ", $parent->error->message ) ); | 
| 180 | 0 |  |  |  |  |  | my $path = $file->file_path; | 
| 181 | 0 |  |  |  |  |  | my $uri = URI->new( $parent->dl_uri ); | 
| 182 | 0 |  |  |  |  |  | $uri->path( $uri->path . '/' . $path ); | 
| 183 | 0 |  |  |  |  |  | my $datadir = File::Spec->tmpdir; | 
| 184 | 0 |  |  |  |  |  | my $tmpdir = File::Temp::tempdir( 'telegram-file-XXXXXXX', DIR => $datadir, CLEANUP => $parent->cleanup_temp ); | 
| 185 |  |  |  |  |  |  | ##( $fh, $file ) = tempfile( "data-XXXXXXX", SUFFIX => ".${ext}", DIR => $tmpdir ); | 
| 186 | 0 |  |  |  |  |  | my $filepath = File::Temp::mktemp( "$tmpdir/data-XXXXXXX" ); | 
| 187 | 0 | 0 |  |  |  |  | $filepath .= '.' . $opts->{ext} if( $opts->{ext} ); | 
| 188 | 0 |  |  |  |  |  | my $req = JDev::HTTP::Request->new( 'GET' => $uri ); | 
| 189 | 0 |  |  |  |  |  | my $res = $parent->agent->request( $req, $filepath ); | 
| 190 | 0 |  |  |  |  |  | my $mime = $res->content_type; | 
| 191 | 0 |  |  |  |  |  | my $len = $res->content_length; | 
| 192 | 0 | 0 |  |  |  |  | if( !$self->is_success ) | 
| 193 |  |  |  |  |  |  | { | 
| 194 | 0 |  |  |  |  |  | return( $self->error( sprintf( "Unable to download file \"$path\". Server returned error code %s (%s)", $res->code, $res->message ) ) ); | 
| 195 |  |  |  |  |  |  | } | 
| 196 | 0 | 0 |  |  |  |  | if( $len != -s( $filepath ) ) | 
| 197 |  |  |  |  |  |  | { | 
| 198 | 0 |  |  |  |  |  | warn( sprintf( "Warning only: The size in bytes returned by the server ($len) is different than the local file (%d)\n", -s( $filepath ) ) ); | 
| 199 |  |  |  |  |  |  | } | 
| 200 | 0 |  |  |  |  |  | my $ext; | 
| 201 | 0 | 0 | 0 |  |  |  | if( !$opts->{ext} && length( $mime ) ) | 
| 202 |  |  |  |  |  |  | { | 
| 203 | 0 | 0 |  |  |  |  | if( $mime =~ /\/([^\/]+)$/ ) | 
| 204 |  |  |  |  |  |  | { | 
| 205 | 0 |  |  |  |  |  | my $ext = $1; | 
| 206 | 0 |  |  |  |  |  | rename( $filepath, "${filepath}.${ext}" ); | 
| 207 | 0 |  |  |  |  |  | $filepath = "${filepath}.${ext}"; | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  | return({ | 
| 211 | 0 |  |  |  |  |  | 'filepath' => $filepath, | 
| 212 |  |  |  |  |  |  | 'mime' => $mime, | 
| 213 |  |  |  |  |  |  | 'response' => $res, | 
| 214 |  |  |  |  |  |  | 'size' => -s( $filepath ), | 
| 215 |  |  |  |  |  |  | }); | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  |  | 
| 218 | 0 |  |  | 0 |  |  | sub _field { return( shift->_set_get( '_field', @_ ) ); } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | sub _get_base_class | 
| 221 |  |  |  |  |  |  | { | 
| 222 | 0 |  |  | 0 |  |  | my $self  = shift( @_ ); | 
| 223 | 0 |  |  |  |  |  | my $class = shift( @_ ); | 
| 224 | 0 |  |  |  |  |  | my $base  = __PACKAGE__; | 
| 225 | 0 |  |  |  |  |  | $base =~ s/\:\:Generic$//; | 
| 226 | 0 |  |  |  |  |  | my $pkg = ( $class =~ /^($base\:\:(?:[^\:]+)?)/ )[0]; | 
| 227 |  |  |  |  |  |  | } | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | # sub _instantiate_object | 
| 230 |  |  |  |  |  |  | # { | 
| 231 |  |  |  |  |  |  | # 	my $self = shift( @_ ); | 
| 232 |  |  |  |  |  |  | #     my $field = shift( @_ ); | 
| 233 |  |  |  |  |  |  | #     my $class = shift( @_ ); | 
| 234 |  |  |  |  |  |  | # 	my $h = | 
| 235 |  |  |  |  |  |  | # 	{ | 
| 236 |  |  |  |  |  |  | # 		'_parent' => $self->{ '_parent' }, | 
| 237 |  |  |  |  |  |  | # 		'_field' => $field, | 
| 238 |  |  |  |  |  |  | # 		'_debug' => $self->{ '_debug' }, | 
| 239 |  |  |  |  |  |  | # 	}; | 
| 240 |  |  |  |  |  |  | # 	$h->{ '_dbh' } = $self->{ '_dbh' } if( $self->{ '_dbh' } ); | 
| 241 |  |  |  |  |  |  | # 	$self->{_parent}->_load( [ $class ] ) || return( $self->error( $self->{_parent}->error->message ) ); | 
| 242 |  |  |  |  |  |  | # 	my $o = @_ ? $class->new( $h, @_ ) : $class->new( $h ); | 
| 243 |  |  |  |  |  |  | # 	return( $self->error( "Unable to instantiate an object of class $class: ", $class->error ) ) if( !defined( $o ) ); | 
| 244 |  |  |  |  |  |  | # 	return( $o ); | 
| 245 |  |  |  |  |  |  | # } | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | sub _instantiate_object | 
| 248 |  |  |  |  |  |  | { | 
| 249 | 0 |  |  | 0 |  |  | my $self = shift( @_ ); | 
| 250 | 0 |  |  |  |  |  | my $name = shift( @_ ); | 
| 251 | 0 | 0 | 0 |  |  |  | return( $self->{ $name } ) if( exists( $self->{ $name } ) && Scalar::Util::blessed( $self->{ $name } ) ); | 
| 252 | 0 |  |  |  |  |  | my $class = shift( @_ ); | 
| 253 |  |  |  |  |  |  | # print( STDERR __PACKAGE__, "::_instantiate_object() called for name '$name' and class '$class'\n" ); | 
| 254 |  |  |  |  |  |  | # $self->message( 3, "called for name '$name' and class '$class'." ); | 
| 255 | 0 |  |  |  |  |  | my $this; | 
| 256 |  |  |  |  |  |  | my $h = | 
| 257 |  |  |  |  |  |  | { | 
| 258 |  |  |  |  |  |  | '_parent' => $self->{_parent}, | 
| 259 |  |  |  |  |  |  | '_field' => $name, | 
| 260 |  |  |  |  |  |  | '_debug' => $self->{debug}, | 
| 261 | 0 |  |  |  |  |  | }; | 
| 262 | 0 | 0 |  |  |  |  | $h->{_dbh} = $self->{_dbh} if( $self->{_dbh} ); | 
| 263 | 0 |  |  |  |  |  | my $o; | 
| 264 | 0 |  |  |  |  |  | try | 
| 265 | 1 |  |  | 1 |  | 404 | { | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | ## https://stackoverflow.com/questions/32608504/how-to-check-if-perl-module-is-available#comment53081298_32608860 | 
| 267 | 0 | 0 |  |  |  |  | eval( "require $class;" ) unless( defined( *{"${class}::"} ) ); | 
|  | 0 |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | # print( STDERR __PACKAGE__, "::_instantiate_object(): Error while loading module $class? $@\n" ); | 
| 269 |  |  |  |  |  |  | # $self->message( 3, "Error while loading module $class? $@" ); | 
| 270 | 0 | 0 |  |  |  |  | return( $self->error( "Unable to load module $class: $@" ) ) if( $@ ); | 
| 271 | 0 | 0 |  |  |  |  | $o = @_ ? $class->new( $h, @_ ) : $class->new( $h ); | 
| 272 | 0 | 0 |  |  |  |  | return( $self->pass_error( "Unable to instantiate an object of class $class: ", $class->error ) ) if( !defined( $o ) ); | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  | catch( $e ) | 
| 275 | 1 | 0 |  | 1 |  | 26626 | { | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | # print( STDERR __PACKAGE__, "::_instantiate_object() An error occured while loading module $class for name '$name': $e\n" ); | 
| 277 | 0 |  |  |  |  |  | return( $self->error({ code => 500, message => $e }) ); | 
| 278 |  |  |  |  |  |  | } | 
| 279 | 0 |  |  |  |  |  | # $self->message( 3, "Returning newly generated object $o with structure: ", $self->dumper( $o ) ); | 
|  | 0 |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | return( $o ); | 
| 281 |  |  |  |  |  |  | } | 
| 282 | 0 |  |  | 0 |  |  |  | 
| 283 |  |  |  |  |  |  | sub _is_boolean { return( 0 ); } | 
| 284 | 0 |  |  | 0 |  |  |  | 
| 285 |  |  |  |  |  |  | sub _message { return( shift->SUPER::message( @_ ) ); } | 
| 286 | 0 |  |  | 0 |  |  |  | 
| 287 |  |  |  |  |  |  | sub _messagef { return( shift->SUPER::messagef( @_ ) ); } | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | sub _object_type_to_class | 
| 290 | 0 |  |  | 0 |  |  | { | 
| 291 | 0 |  | 0 |  |  |  | my $self = shift( @_ ); | 
| 292 | 0 |  |  |  |  |  | my $type = shift( @_ ) || return( $self->error( "No object type was provided" ) ); | 
| 293 | 0 |  |  |  |  |  | my $ref  = $Net::API::Telegram::TYPE2CLASS; | 
| 294 | 0 | 0 |  |  |  |  | $self->_messagef( 3, "\$TYPE2CLASS has %d elements", scalar( keys( %$ref ) ) ); | 
| 295 | 0 |  |  |  |  |  | return( $self->error( "No object type '$type' known to get its related class for field $self->{_field}" ) ) if( !exists( $ref->{ $type } ) ); | 
| 296 |  |  |  |  |  |  | return( $ref->{ $type } ); | 
| 297 |  |  |  |  |  |  | } | 
| 298 | 0 |  |  | 0 |  |  |  | 
| 299 |  |  |  |  |  |  | sub _parent { return( shift->_set_get( '_parent', @_ ) ); } | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | sub _set_get_hash | 
| 302 | 0 |  |  | 0 |  |  | { | 
| 303 | 0 |  |  |  |  |  | my $self = shift( @_ ); | 
| 304 | 0 |  |  |  |  |  | my $field = shift( @_ ); | 
| 305 | 0 |  |  |  |  |  | my $class = $field; | 
| 306 | 0 |  |  |  |  |  | $class =~ tr/-/_/; | 
| 307 | 0 |  |  |  |  |  | $class =~ s/\_{2,}/_/g; | 
| 308 | 0 |  |  |  |  |  | $class = join( '', map( ucfirst( lc( $_ ) ), split( /\_/, $class ) ) ); | 
| 309 |  |  |  |  |  |  | return( $self->_set_get_hash_as_object( $field, $class, @_ ) ); | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | sub _set_get_number | 
| 313 | 0 |  |  | 0 |  |  | { | 
| 314 | 0 |  |  |  |  |  | my $self  = shift( @_ ); | 
| 315 | 0 | 0 |  |  |  |  | my $field = shift( @_ ); | 
| 316 |  |  |  |  |  |  | if( @_ ) | 
| 317 | 0 |  |  |  |  |  | { | 
| 318 |  |  |  |  |  |  | $self->{ $field } = Net::API::Telegram::Number->new( shift( @_ ) ); | 
| 319 | 0 |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | return( $self->{ $field } ); | 
| 321 |  |  |  |  |  |  | } | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | sub _set_get_number_or_object | 
| 324 | 0 |  |  | 0 |  |  | { | 
| 325 | 0 |  |  |  |  |  | my $self  = shift( @_ ); | 
| 326 | 0 |  |  |  |  |  | my $field = shift( @_ ); | 
| 327 | 0 | 0 |  |  |  |  | my $class = shift( @_ ); | 
| 328 |  |  |  |  |  |  | if( @_ ) | 
| 329 | 0 | 0 | 0 |  |  |  | { | 
| 330 |  |  |  |  |  |  | if( ref( $_[0] ) eq 'HASH' || Scalar::Util::blessed( $_[0] ) ) | 
| 331 | 0 |  |  |  |  |  | { | 
| 332 |  |  |  |  |  |  | return( $self->_set_get_object( $field, $class, @_ ) ); | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  | else | 
| 335 | 0 |  |  |  |  |  | { | 
| 336 |  |  |  |  |  |  | return( $self->_set_get_number( $field, @_ ) ); | 
| 337 |  |  |  |  |  |  | } | 
| 338 | 0 |  |  |  |  |  | } | 
| 339 |  |  |  |  |  |  | return( $self->{ $field } ); | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | sub _set_get_object_array2 | 
| 343 | 0 |  |  | 0 |  |  | { | 
| 344 | 0 |  |  |  |  |  | my $self  = shift( @_ ); | 
| 345 | 0 |  |  |  |  |  | my $field = shift( @_ ); | 
| 346 | 0 | 0 |  |  |  |  | my $class = shift( @_ ); | 
| 347 |  |  |  |  |  |  | if( @_ ) | 
| 348 | 0 |  |  |  |  |  | { | 
| 349 | 0 | 0 |  |  |  |  | my $this = shift( @_ ); | 
| 350 | 0 |  |  |  |  |  | return( $self->error( "I was expecting an array ref, but instead got '$this'" ) ) if( ref( $this ) ne 'ARRAY' ); | 
| 351 | 0 |  |  |  |  |  | my $arr1 = []; | 
| 352 |  |  |  |  |  |  | foreach my $ref ( @$this ) | 
| 353 | 0 | 0 |  |  |  |  | { | 
| 354 | 0 |  |  |  |  |  | return( $self->error( "I was expecting an embeded array ref, but instead got '$ref'." ) ) if( ref( $ref ) ne 'ARRAY' ); | 
| 355 | 0 |  |  |  |  |  | my $arr = []; | 
| 356 |  |  |  |  |  |  | for( my $i = 0; $i < scalar( @$ref ); $i++ ) | 
| 357 | 0 |  |  |  |  |  | { | 
| 358 | 0 | 0 |  |  |  |  | my $o; | 
| 359 |  |  |  |  |  |  | if( defined( $ref->[$i] ) ) | 
| 360 | 0 | 0 |  |  |  |  | { | 
| 361 | 0 | 0 |  |  |  |  | return( $self->error( "Parameter provided for adding object of class $class is not a reference." ) ) if( !ref( $ref->[$i] ) ); | 
|  |  | 0 |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | if( Scalar::Util::blessed( $ref->[$i] ) ) | 
| 363 | 0 |  |  |  |  |  | { | 
| 364 | 0 | 0 |  |  |  |  | my $pack = $ref->[$i]->isa( $class ); | 
| 365 |  |  |  |  |  |  | if( $pack ) | 
| 366 | 0 |  |  |  |  |  | { | 
| 367 | 0 |  |  |  |  |  | $o->{_parent} = $self->{_parent}; | 
| 368 | 0 | 0 |  |  |  |  | $o->{_debug} = $self->{_debug}; | 
| 369 | 0 |  |  |  |  |  | $o->{_dbh} = $self->{_dbh} if( $self->{_dbh} ); | 
| 370 |  |  |  |  |  |  | $o = $ref->[$i]; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  | else | 
| 373 | 0 |  |  |  |  |  | { | 
| 374 |  |  |  |  |  |  | return( $self->error( "Object provided ($pack) is not a $class object" ) ); | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  | elsif( ref( $ref->[$i] ) eq 'HASH' ) | 
| 378 | 0 |  |  |  |  |  | { | 
| 379 |  |  |  |  |  |  | $o = $self->_instantiate_object( $field, $class, $ref->[$i] ); | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  | else | 
| 382 | 0 |  |  |  |  |  | { | 
| 383 |  |  |  |  |  |  | $self->error( "Warning only: data provided to instaantiate object of class $class is not a hash reference" ); | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  | } | 
| 386 |  |  |  |  |  |  | else | 
| 387 | 0 |  |  |  |  |  | { | 
| 388 |  |  |  |  |  |  | $o = $self->_instantiate_object( $field, $class ); | 
| 389 | 0 | 0 |  |  |  |  | } | 
| 390 | 0 |  |  |  |  |  | return( $self->error( "Unable to instantiate an object of class $class: ", $class->error ) ) if( !defined( $o ) ); | 
| 391 |  |  |  |  |  |  | push( @$arr, $o ); | 
| 392 | 0 |  |  |  |  |  | } | 
| 393 |  |  |  |  |  |  | push( @$arr1, $arr ); | 
| 394 | 0 |  |  |  |  |  | } | 
| 395 |  |  |  |  |  |  | $self->{ $field } = $arr1; | 
| 396 | 0 |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  | return( $self->{ $field } ); | 
| 398 |  |  |  |  |  |  | } | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | sub _set_get_object_array | 
| 401 | 0 |  |  | 0 |  |  | { | 
| 402 | 0 |  |  |  |  |  | my $self  = shift( @_ ); | 
| 403 | 0 |  |  |  |  |  | my $field = shift( @_ ); | 
| 404 | 0 | 0 |  |  |  |  | my $class = shift( @_ ); | 
| 405 |  |  |  |  |  |  | if( @_ ) | 
| 406 | 0 |  |  |  |  |  | { | 
| 407 | 0 | 0 |  |  |  |  | my $ref = shift( @_ ); | 
| 408 | 0 |  |  |  |  |  | return( $self->error( "I was expecting an array ref, but instead got '$ref'" ) ) if( ref( $ref ) ne 'ARRAY' ); | 
| 409 | 0 |  |  |  |  |  | my $arr = []; | 
| 410 |  |  |  |  |  |  | for( my $i = 0; $i < scalar( @$ref ); $i++ ) | 
| 411 | 0 |  |  |  |  |  | { | 
| 412 |  |  |  |  |  |  | $self->_message( 3, "Calling method $class->$field with value '", $ref->[$i], "'" ); | 
| 413 |  |  |  |  |  |  | ## Either the value provided is not defined, and we just instantiate an empty object, or | 
| 414 |  |  |  |  |  |  | ## the value is a hash and we instantiate a new object with those parameters, or | 
| 415 |  |  |  |  |  |  | ## we have been provided an existing object | 
| 416 | 0 |  |  |  |  |  | ## my $o = defined( $ref->[$i] ) ? $class->new( $h, $ref->[$i] ) : $class->new( $h ); | 
| 417 | 0 | 0 |  |  |  |  | my $o; | 
| 418 |  |  |  |  |  |  | if( defined( $ref->[$i] ) ) | 
| 419 | 0 | 0 |  |  |  |  | { | 
| 420 | 0 | 0 |  |  |  |  | return( $self->error( "Parameter provided for adding object of class $class is not a reference." ) ) if( !ref( $ref->[$i] ) ); | 
|  |  | 0 |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | if( Scalar::Util::blessed( $ref->[$i] ) ) | 
| 422 | 0 |  |  |  |  |  | { | 
| 423 | 0 | 0 |  |  |  |  | my $pack = $ref->[$i]->isa( $class ); | 
| 424 |  |  |  |  |  |  | if( $pack ) | 
| 425 | 0 |  |  |  |  |  | { | 
| 426 | 0 |  |  |  |  |  | $o->{_parent} = $self->{_parent}; | 
| 427 | 0 | 0 |  |  |  |  | $o->{_debug} = $self->{debug}; | 
| 428 | 0 |  |  |  |  |  | $o->{_dbh} = $self->{_dbh} if( $self->{_dbh} ); | 
| 429 |  |  |  |  |  |  | $o = $ref->[$i]; | 
| 430 |  |  |  |  |  |  | } | 
| 431 |  |  |  |  |  |  | else | 
| 432 | 0 |  |  |  |  |  | { | 
| 433 |  |  |  |  |  |  | return( $self->error( "Object provided ($pack) is not a $class object" ) ); | 
| 434 |  |  |  |  |  |  | } | 
| 435 |  |  |  |  |  |  | } | 
| 436 |  |  |  |  |  |  | elsif( ref( $ref->[$i] ) eq 'HASH' ) | 
| 437 |  |  |  |  |  |  | { | 
| 438 | 0 |  |  |  |  |  | #$o = $class->new( $h, $ref->[$i] ); | 
| 439 |  |  |  |  |  |  | $o = $self->_instantiate_object( $field, $class, $ref->[$i] ); | 
| 440 |  |  |  |  |  |  | } | 
| 441 |  |  |  |  |  |  | else | 
| 442 | 0 |  |  |  |  |  | { | 
| 443 |  |  |  |  |  |  | $self->error( "Warning only: data provided to instaantiate object of class $class is not a hash reference" ); | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  | else | 
| 447 | 0 |  |  |  |  |  | { | 
| 448 |  |  |  |  |  |  | $o = $self->_instantiate_object( $field, $class ); | 
| 449 | 0 | 0 |  |  |  |  | } | 
| 450 | 0 |  |  |  |  |  | return( $self->error( "Unable to instantiate an object of class $class: ", $class->error ) ) if( !defined( $o ) ); | 
| 451 |  |  |  |  |  |  | push( @$arr, $o ); | 
| 452 | 0 |  |  |  |  |  | } | 
| 453 |  |  |  |  |  |  | $self->{ $field } = $arr; | 
| 454 | 0 |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  | return( $self->{ $field } ); | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | sub _set_get_object_variant | 
| 459 | 0 |  |  | 0 |  |  | { | 
| 460 | 0 |  |  |  |  |  | my $self = shift( @_ ); | 
| 461 |  |  |  |  |  |  | my $field = shift( @_ ); | 
| 462 |  |  |  |  |  |  | ## The class precisely depends on what we find looking ahead | 
| 463 | 0 | 0 |  |  |  |  | ## my $class = shift( @_ ); | 
| 464 |  |  |  |  |  |  | if( @_ ) | 
| 465 |  |  |  |  |  |  | { | 
| 466 |  |  |  |  |  |  | local $process = sub | 
| 467 | 0 |  |  | 0 |  |  | { | 
| 468 | 0 |  | 0 |  |  |  | my $ref = shift( @_ ); | 
| 469 | 0 |  |  |  |  |  | my $type = $ref->{ 'object' } || return( $self->error( "No object type could be found in hash: ", sub{ $self->_dumper( $ref ) } ) ); | 
| 470 | 0 |  |  |  |  |  | my $class = $self->_object_type_to_class( $type ); | 
| 471 | 0 |  |  |  |  |  | $self->_message( 3, "Object type $type has class $class" ); | 
| 472 | 0 |  |  |  |  |  | my $o = $self->_instantiate_object( $field, $class, $ref ); | 
| 473 |  |  |  |  |  |  | $self->{ $field } = $o; | 
| 474 |  |  |  |  |  |  | ## return( $class->new( %$ref ) ); | 
| 475 | 0 |  |  |  |  |  | ## return( $self->_set_get_object( 'object', $class, $ref ) ); | 
| 476 |  |  |  |  |  |  | }; | 
| 477 | 0 | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | if( ref( $_[0] ) eq 'HASH' ) | 
| 479 | 0 |  |  |  |  |  | { | 
| 480 |  |  |  |  |  |  | my $o = $process->( @_ ) | 
| 481 |  |  |  |  |  |  | } | 
| 482 |  |  |  |  |  |  | ## AN array of objects hash | 
| 483 |  |  |  |  |  |  | elsif( ref( $_[0] ) eq 'ARRAY' ) | 
| 484 | 0 |  |  |  |  |  | { | 
| 485 | 0 |  |  |  |  |  | my $arr = shift( @_ ); | 
| 486 | 0 |  |  |  |  |  | my $res = []; | 
| 487 |  |  |  |  |  |  | foreach my $data ( @$arr ) | 
| 488 | 0 |  | 0 |  |  |  | { | 
| 489 | 0 |  |  |  |  |  | my $o = $process->( $data ) || return( $self->error( "Unable to create object: ", $self->error ) ); | 
| 490 |  |  |  |  |  |  | push( @$res, $o ); | 
| 491 | 0 |  |  |  |  |  | } | 
| 492 |  |  |  |  |  |  | $self->{ $field } = $res; | 
| 493 |  |  |  |  |  |  | } | 
| 494 | 0 |  |  |  |  |  | } | 
| 495 |  |  |  |  |  |  | return( $self->{ $field } ); | 
| 496 |  |  |  |  |  |  | } | 
| 497 |  |  |  |  |  |  |  | 
| 498 |  |  |  |  |  |  | 1; | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | __END__ | 
| 501 |  |  |  |  |  |  |  |