Files
seatmapv1/seatmap-server/seatmap-server.pl
2021-01-20 18:31:29 +01:00

692 lines
28 KiB
Perl
Executable File

#!/usr/bin/env perl
use strict;
use warnings;
use CGI ":standard";
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
use Data::Dumper;
use LWP::UserAgent ();
use XML::LibXML;
use Encode;
use URI;
use Benchmark;
use JSON;
use utf8;
use feature qw/say/;
use Encode::Deep;
use DBD::mysql;
use URI::Encode qw(uri_encode uri_decode);
use URI::Split qw(uri_split uri_join);
use Data::Dumper;
use HTML::TreeBuilder::XPath;
# LWP
my $ua = LWP::UserAgent->new(keep_alive => 1);
$ua->agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36');
$ua->timeout(10);
$ua->env_proxy;
# CGI
my $cgi = CGI->new;
# GLOBAL
my %CONFIG =
(
'DEBUG' => 0,
'DEBUG_PRINT_DATA' => 0,
'ONLINE' => 1,
'USE_CORSANYWHERE' => 0,
'OFFLINE_XML' => '../seatmap-client/offline/MapTicketSales.xml',
'OFFLINE_XML_PARKETT' => '../seatmap-client/offline/MapTicketSales_Parkett.xml',
'OFFLINE_XML_RANG' => '../seatmap-client/offline/MapTicketSales_Rang.xml',
'MYSQL' => {
'database' => 'seatmap',
'hostname' => 'localhost',
'user' => 'seatmap',
'pw' => 'EGNSOp6DE1xd7wMN',
'port' => 3306,
},
);
my %DATA;
my $connection;
# WORKFLOW
my $t0 = Benchmark->new if $CONFIG{'DEBUG'};
&getParameter();
print Dumper $DATA{'PARAMETER'} if $CONFIG{'DEBUG'};
&checkHost();
if( $DATA{'PARAMETER'}{'request_switch'} eq 'seatmapWorkflow' ) {
say 'Switch seatmapWorkflow' if ($CONFIG{'DEBUG'});
&generateVenueUrl();
my $xml;
if ($CONFIG{'ONLINE'}) {
print "SET AS ONLINE\n" if $CONFIG{'DEBUG'};
$xml = &get($DATA{'PARAMETER'}{'urlVenue'});
&loadXML($xml, \$DATA{'DOM'});
&parseXML();
&getSeatmaps();
}
elsif (!$CONFIG{'ONLINE'}) {
print "SET AS OFFLINE: USING LOCAL XML\n" if $CONFIG{'DEBUG'};
$xml = $CONFIG{'OFFLINE_XML'};
&loadXML($xml, \$DATA{'DOM'});
&parseXML();
&loadXML($CONFIG{'OFFLINE_XML_PARKETT'}, \$DATA{'DOM'});
parxeXML_section();
&loadXML($CONFIG{'OFFLINE_XML_RANG'}, \$DATA{'DOM'});
parxeXML_section();
}
my $config_ref = &getVenueConfig();
&printOutput($config_ref);
}
elsif( $DATA{'PARAMETER'}{'request_switch'} eq 'checkoutCheckResponse' ) {
say 'Switch checkoutCheckResponse' if ($CONFIG{'DEBUG'});
my $decoded_content = &get($DATA{'PARAMETER'}{'url'});
#print Dumper $decoded_content;
my $tree = HTML::TreeBuilder::XPath->new_from_content($decoded_content);
my $xpath_alert = '//input[@id="no_timeout_error_msg"]/@value';
if ($tree->exists($xpath_alert)) {
#my $alert = decode('utf-8', trim($tree->findvalue($xpath_alert)));
my %alert;
$alert{'no_timeout_error_msg'}{'value'} = trim($tree->findvalue($xpath_alert));
$alert{'no_timeout_error_msg'}{'id'} = 'no_timeout_error_msg';
if (!$CONFIG{'DEBUG'}) {
print header(
-type => 'application/json',
-access_control_allow_origin => '*',
-charset => 'utf-8',
);
# OUTPUT JSON
print encode_json \%alert;
}
elsif ($CONFIG{'DEBUG'}) {
print Dumper \%alert;
}
}
}
&benchmarkEnd() if ($CONFIG{'DEBUG'});
# SUBS
sub trim {
my $string = shift;
$string =~ s/^\s+|\s+$//g;
return $string;
}
sub db_getVenueConfig {
&Delimiter((caller(0))[3]);
my $query = "Select \
venues.AGENCY As VENUE_AGENCY,
venues.NAME As VENUE_NAME,
halls.NAME As HALL_NAME,
halls.CODE As HALL_CODE,
halls.`FRONT-INDICATOR_WIDTH` As HALL_FRONT_INDICATOR,
halls.`PADDING-LEFT` As HALL_PADDING_LEFT,
halls.`PADDING-LEFT-STAGE` As HALL_PADDING_LEFT_STAGE,
halls.MAX_TICKETS_PER_USER As HALL_MAX_TICKETS_PER_USER,
halls.BUEHNE As HALL_BUEHNE,
halls.LEFT_NAMING As HALL_LEFT_NAMING,
halls.TONPULT As HALL_TONPULT,
halls.CSS As HALL_CSS,
halls.DESCRIPTION As HALL_DESC,
buyer_types.CODE As BUYER_TYPE_CODE,
buyer_types.DESCRIPTION As BUYER_TYPE_DESC,
halls.ID As HALL_ID
From
venues Inner Join
halls On halls.VENUE_ID = venues.ID Inner Join
buyer_types On buyer_types.VENUE_ID = halls.VENUE_ID
Where
venues.AGENCY = '$DATA{'PARAMETER'}{'supplier_code'}'";
print Dumper $query if $CONFIG{'DEBUG'};
my $response = &db_query($query, $connection, 'selectall_arrayref');
my $query_config = "SELECT * FROM config";
print Dumper $query_config if $CONFIG{'DEBUG'};
my $response_config = &db_query($query_config, $connection, 'selectall_hashref', 'NAME');
return ($response, $response_config);
}
sub accumulate_halls_data {
&Delimiter((caller(0))[3]);
my ($response) = @_;
my %halls;
for my $i (0 .. $#{$response}) {
# print Dumper $$response[$i];
my $hall_code = $$response[$i][3];
$halls{$hall_code}{'VENUE_AGENCY'} = $$response[$i][0];
$halls{$hall_code}{'VENUE_NAME'} = $$response[$i][1];
$halls{$hall_code}{'HALL_NAME'} = $$response[$i][2];
$halls{$hall_code}{'HALL_CODE'} = $$response[$i][3];
$halls{$hall_code}{'HALL_FRONT_INDICATOR'} = $$response[$i][4];
$halls{$hall_code}{'HALL_PADDING_LEFT'} = $$response[$i][5];
$halls{$hall_code}{'HALL_PADDING_LEFT_STAGE'} = $$response[$i][6];
$halls{$hall_code}{'HALL_MAX_TICKETS_PER_USER'} = $$response[$i][7];
$halls{$hall_code}{'HALL_BUEHNE'} = $$response[$i][8];
$halls{$hall_code}{'HALL_LEFT_NAMING'} = $$response[$i][9];
$halls{$hall_code}{'HALL_TONPULT'} = $$response[$i][10];
$halls{$hall_code}{'HALL_CSS'} = $$response[$i][11];
$halls{$hall_code}{'HALL_DESC'} = $$response[$i][12];
$halls{$hall_code}{'BUYER_TYPES'}{$$response[$i][13]} = $$response[$i][14];
$halls{$hall_code}{'HALL_ID'} = $$response[$i][15];
my $hall_id = $$response[0][15];
my $query_color = "SELECT * FROM custom_pricescales_color WHERE HALL_ID = $halls{$hall_code}{'HALL_ID'}";
print Dumper $query_color if $CONFIG{'DEBUG'};
my $response_color = &db_query($query_color, $connection, 'selectall_hashref', 'ID');
if (%$response_color) {
$halls{$hall_code}{'CUSTOM_PRICESCALES_COLOR'} = $response_color;
}
};
return \%halls;
}
sub convert_to_config_format {
&Delimiter((caller(0))[3]);
my ($halls_ref, $response_config) = @_;
my %seatmap_config;
for my $hall_code (keys %{$halls_ref}) {
my $hall_name = $$halls_ref{$hall_code}{'HALL_NAME'};
$seatmap_config{$hall_code} = # HALL CONFIG
{
"FRONT-INDICATOR-WIDTH" => $$halls_ref{$hall_code}{'HALL_FRONT_INDICATOR'},
"PADDING-LEFT" => $$halls_ref{$hall_code}{'HALL_PADDING_LEFT'},
"PADDING-LEFT-STAGE" => $$halls_ref{$hall_code}{'HALL_PADDING_LEFT_STAGE'},
"MAX_TICKETS_PER_USER" => $$halls_ref{$hall_code}{'HALL_MAX_TICKETS_PER_USER'},
"BUEHNE" => $$halls_ref{$hall_code}{'HALL_BUEHNE'},
"LEFT_NAMING" => $$halls_ref{$hall_code}{'HALL_LEFT_NAMING'},
"CSS" => $$halls_ref{$hall_code}{'HALL_CSS'},
};
$seatmap_config{$hall_name} = # HALL BUYER TYPES
{
"AGENCY" => $$halls_ref{$hall_code}{'VENUE_AGENCY'},
"BUYER_TYPES" => $$halls_ref{$hall_code}{'BUYER_TYPES'},
};
if ($$halls_ref{$hall_code}{'CUSTOM_PRICESCALES_COLOR'}) {
for my $id (keys %{$$halls_ref{$hall_code}{'CUSTOM_PRICESCALES_COLOR'}}) {
my $code = $$halls_ref{$hall_code}{'CUSTOM_PRICESCALES_COLOR'}{$id}{'CODE'};
my $color = $$halls_ref{$hall_code}{'CUSTOM_PRICESCALES_COLOR'}{$id}{'COLOR'};
$seatmap_config{$hall_code}{'CUSTOM_PRICESCALES_COLOR'}{$code} = $color;
};
}
}
for my $key (keys %$response_config) {
if ($key eq 'CORS_ANYWHERE') {
$seatmap_config{'CORS-ANYWHERE'}{'ROOT_URL'} = $$response_config{$key}{'VALUE'};
}
else {
$seatmap_config{$key} = $$response_config{$key}{'VALUE'};
}
};
return \%seatmap_config;
}
sub getVenueConfig {
&Delimiter((caller(0))[3]);
# CONNECT TO DB
$connection = connectToMySql();
# GET DB DATA FOR VENUE / HALLS / BUYER TYPES
my ($response, $response_config) = db_getVenueConfig();
# CREATE ONE DATASET AND ACCUMULATE ALL BUYER TYPES FOR HALL
my $halls_ref = &accumulate_halls_data($response);
# print Dumper $halls_ref;
# CONVERT DATA TO STEAMAP CONFIG FORMAT
my $seatmap_config_ref = convert_to_config_format($halls_ref, $response_config);
# DISCONNECT FROM DB
$connection->disconnect();
return $seatmap_config_ref;
}
sub db_query {
&Delimiter((caller(0))[3]);
my ($query, $connection, $switch, @rest) = @_;
my $response;
my $statement;
if ($switch eq 'fetchrow') {
$statement = $connection->prepare($query);
$statement->execute();
$response = $statement->fetchrow();
}
elsif ($switch eq 'fetchall_hashref') {
$statement = $connection->prepare($query);
$statement->execute();
$response = $statement->fetchall_hashref($rest[0]);
}
elsif ($switch eq 'fetchall_arrayref') {
$statement = $connection->prepare($query);
$statement->execute();
$response = $statement->fetchall_arrayref();
}
elsif ($switch eq 'do') {
$response = $connection->do($query) or die $connection->errstr;
}
elsif ($switch eq 'selectall_hashref') {
$response = $connection->selectall_hashref($query, $rest[0]) or die $connection->errstr;
}
elsif ($switch eq 'selectall_array') {
my @response = $connection->selectall_array($query) or die $connection->errstr;
return \@response;
}
elsif ($switch eq 'selectall_arrayref') {
$response = $connection->selectall_arrayref($query) or die $connection->errstr;
}
elsif ($switch eq 'selectrow_hashref') {
$response = $connection->selectrow_hashref($query) or die $connection->errstr;
}
$statement->finish if $statement;
return $response;
}
sub connectToMySql {
&Delimiter((caller(0))[3]);
my $connectionInfo = "dbi:mysql:$CONFIG{'MYSQL'}{'database'};$CONFIG{'MYSQL'}{'hostname'}";
# make connection to database
my $connection = DBI->connect($connectionInfo, $CONFIG{'MYSQL'}{'user'}, $CONFIG{'MYSQL'}{'pw'}, {
RaiseError => 0, # SUGGESTED BY AnyEvent::DBI::MySQL
AutoCommit => 1,
mysql_auto_reconnect => 1,
});
return $connection;
}
sub wipeDataOverhead {
&Delimiter((caller(0))[3]);
delete $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{'AVAILABILITY'};
for my $pricescaleID (keys(%{$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}})) {
delete $DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'SEATS'};
}
}
sub printOutput {
my $config_ref = shift;
if (!$CONFIG{'DEBUG'}) {
&wipeDataOverhead();
# print header('application/json; charset=utf-8;'), encode_json $DATA{'COMPILED'};
print header(
-type => 'application/json',
-access_control_allow_origin => '*',
-charset => 'utf-8',
);
# FIX ENCODING
$DATA{'COMPILED'} = Encode::Deep::decode('utf-8', Encode::Deep::encode('cp850', $DATA{'COMPILED'}));
# my $encoded = Encode::Deep::encode('cp850', $DATA{'COMPILED'});
# my $decoded = Encode::Deep::decode('utf-8', $encoded);
# ADD SEATMAP CONFIG
$DATA{'COMPILED'}{'CONFIG'} = $config_ref;
# OUTPUT JSON
print encode_json $DATA{'COMPILED'};
}
elsif ($CONFIG{'DEBUG'} && $CONFIG{'DEBUG_PRINT_DATA'}) {
&Delimiter((caller(0))[3]);
print "\n\n" . encode_json $DATA{'COMPILED'};
# print "\n\n" . Dumper(\%DATA);
}
}
sub checkHost() {
&Delimiter((caller(0))[3]);
return if !$CONFIG{'ONLINE'};
my $URI = URI->new($DATA{'PARAMETER'}{'url'}, 'http');
if (($URI->host() eq 'purchase.tickets.com') && $URI->scheme && $DATA{'PARAMETER'}{'url'}) {
print "VALID HOST\n" if $CONFIG{'DEBUG'};
}
else {
die "INVALID OR MISSING HOST.\n";
}
}
sub benchmarkEnd() {
&Delimiter((caller(0))[3]);
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "BENCHMARK: ",timestr($td),"\n" if $CONFIG{'DEBUG'};
}
sub generateVenueUrl() {
&Delimiter((caller(0))[3]);
return if !$CONFIG{'ONLINE'};
$DATA{'PARAMETER'}{'urlVenue'} = $DATA{'PARAMETER'}{'url'} . "&supplier_code=$DATA{'PARAMETER'}{'supplier_code'}&bots_event_code=$DATA{'PARAMETER'}{'bots_event_code'}&event_sub_code=$DATA{'PARAMETER'}{'event_sub_code'}" . "&holdcode=0&event=$DATA{'PARAMETER'}{'event'}&nocache=0&inclpkg=Y&incloffer=Y&inclcartdetails=Y&inclCart=Y&inclvenue=Y";
}
sub getSeatmaps() {
&Delimiter((caller(0))[3]);
for my $seatmapID (keys(%{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}})) {
my $url = $DATA{'PARAMETER'}{'url'} . "&supplier_code=$DATA{'PARAMETER'}{'supplier_code'}&bots_event_code=$DATA{'PARAMETER'}{'bots_event_code'}&event_sub_code=$DATA{'PARAMETER'}{'event_sub_code'}" . "&event=$DATA{'PARAMETER'}{'event'}&nocache=1&inclsection=Y&incloffer=Y&offer=0&inclseatmap=Y&inclCart=Y&holdcode=0&seatmap=$seatmapID";
print "GET SEATMAP $seatmapID...\n" if $CONFIG{'DEBUG'};
&loadXML(get($url), \$DATA{'DOM'});
parxeXML_section();
}
}
sub parxeXML_section {
&Delimiter((caller(0))[3]);
my $id = $DATA{'DOM'}->findvalue('//seatmap/@id');
#print "ID: $id\n";
# CREATE PRICE ARRAYS
foreach my $node ($DATA{'DOM'}->findnodes('//pricescale_config/pricescale')) {
my $pricescaleID = $node->findvalue('@id');
@{$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'SEATS'}} = split /,/, $node->findvalue('@mask');
}
# CREATE AVAILABILITY ARRAYS
@{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{'AVAILABILITY'}{'AVAILABLE'}} = split /,/, $DATA{'DOM'}->findvalue('//availability/@available_selectable_mask');
@{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{'AVAILABILITY'}{'UNAVAILABLE'}} = split /,/, $DATA{'DOM'}->findvalue('//availability/@unavailable_unselectable_mask');
# CREATE SEATMAP_CONFIG ROWS
my $rowCalculated = 0;
foreach my $node ($DATA{'DOM'}->findnodes('//rows/row')) {
$rowCalculated++;
my @seats = split /\|/, $node->findvalue('@seats');
my $yCoord = $node->findvalue('@y_cell_coord');
#print Dumper(@seats);
my $seatNR = 0;
foreach my $i (0 .. $#seats) {
$seatNR++;
my ($id1, $id2, $number, $sectionID, $row, $seatNR_parsed) = split /,/, $seats[$i];
#print "ID1: $id1 ID2: $id2 NUMBER: $number SECTIONID: $sectionID ROW: $rowCalculated SEATNR: $seatNR\n";
$row =~ s/\s+$//;
($DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ID1'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'X_COORD'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'SECTIONID'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ROW'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'SEATNR'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'Y_COORD'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ROW_PARSED'}, $DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'SEATNR_PARSED'}) = ($id1, $number, $sectionID, $rowCalculated, $seatNR, $yCoord, $row, $seatNR_parsed);
# SECTION DESC
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'SECTIONID_DESC'} = $DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$sectionID}{'DESC'};
# CHECK PRICE AND ADD COLOR
for my $pricescaleID (keys(%{$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}})) {
if ( grep( /^$id1$/, @{$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'SEATS'}} ) ) {
#print "found it for price $DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'PRICES'}{'REF_PRICE'}\n";
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'PRICESCALES_ID'} = $pricescaleID;
#%{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'PRICES'}} = %{$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'PRICES'}};
#$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'COLOR'} = $DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$pricescaleID}{'COLOR'};
}
}
# CHECK AVAILABILITY
if ( grep( /^$id1$/, @{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{'AVAILABILITY'}{'AVAILABLE'}} ) ) {
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'AVAILABLE'} = 1;
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ENABLED'} = 1;
}
elsif ( grep( /^$id1$/, @{$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{'AVAILABILITY'}{'UNAVAILABLE'}} ) ) {
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'AVAILABLE'} = 0;
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ENABLED'} = 1;
}
else {
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'AVAILABLE'} = 0;
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ROWS'}{$rowCalculated}{$seatNR}{'ENABLED'} = 0;
}
}
}
}
sub substituteUmlauts {
&Delimiter((caller(0))[3]);
my $string_ref = shift;
$$string_ref =~ s/\x{251c}\x{255d}/ue/ if $$string_ref =~ /\x{251c}\x{255d}/;
$$string_ref =~ s/\x{251c}\x{2562}/oe/ if $$string_ref =~ /\x{251c}\x{2562}/;
$$string_ref =~ s/\x{251c}\x{f1}/ae/ if $$string_ref =~ /\x{251c}\x{f1}/;
$$string_ref =~ s/\x{251c}\x{cd}/a/ if $$string_ref =~ /\x{251c}\x{cd}/;
$$string_ref = uc($$string_ref);
}
sub fix_encoding() {
my $string = shift;
return decode('utf-8', encode('cp850', $string));
}
sub parseXML {
&Delimiter((caller(0))[3]);
# EVENT
$DATA{'COMPILED'}{'EVENT'}{'ID'} = $DATA{'DOM'}->findvalue('//event/@id');
$DATA{'COMPILED'}{'EVENT'}{'CODE'} = $DATA{'DOM'}->findvalue('//event/@code');
$DATA{'COMPILED'}{'EVENT'}{'DESC'} = $DATA{'DOM'}->findvalue('//event/@desc');
# $DATA{'COMPILED'}{'EVENT'}{'DESC'} = &fix_encoding($DATA{'COMPILED'}{'EVENT'}{'DESC'});
# &substituteUmlauts(\$DATA{'COMPILED'}{'EVENT'}{'DESC'});
$DATA{'COMPILED'}{'EVENT'}{'PUBLIC_DESC'} = $DATA{'DOM'}->findvalue('//event/@public_desc');
# &substituteUmlauts(\$DATA{'COMPILED'}{'EVENT'}{'PUBLIC_DESC'});
$DATA{'COMPILED'}{'EVENT'}{'YEAR'} = $DATA{'DOM'}->findvalue('//event/@year');
$DATA{'COMPILED'}{'EVENT'}{'MONTH'} = $DATA{'DOM'}->findvalue('//event/@month');
$DATA{'COMPILED'}{'EVENT'}{'DAY'} = $DATA{'DOM'}->findvalue('//event/@day');
$DATA{'COMPILED'}{'EVENT'}{'HOUR'} = $DATA{'DOM'}->findvalue('//event/@hour');
$DATA{'COMPILED'}{'EVENT'}{'MINUTE'} = $DATA{'DOM'}->findvalue('//event/@minute');
$DATA{'COMPILED'}{'EVENT'}{'DATETIME_DE'} = "$DATA{'COMPILED'}{'EVENT'}{'DAY'}.$DATA{'COMPILED'}{'EVENT'}{'MONTH'}.$DATA{'COMPILED'}{'EVENT'}{'YEAR'} $DATA{'COMPILED'}{'EVENT'}{'HOUR'}:$DATA{'COMPILED'}{'EVENT'}{'MINUTE'}";
# VENUE
$DATA{'COMPILED'}{'VENUE'}{'CODE'} = $DATA{'DOM'}->findvalue('//venue/@code');
$DATA{'COMPILED'}{'VENUE'}{'DESC'} = $DATA{'DOM'}->findvalue('//venue/@desc');
$DATA{'COMPILED'}{'VENUE'}{'NAME'} = $DATA{'DOM'}->findvalue('//venue/@name');
$DATA{'COMPILED'}{'VENUE'}{'ID'} = $DATA{'DOM'}->findvalue('//venue/@id');
# VENUE PRICESCALES
foreach my $node ($DATA{'DOM'}->findnodes('//pricescales/pricescale')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'ID'} = $id;
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'CODE'} = $node->findvalue('@code');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'COLOR'} = $node->findvalue('@color');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'DESC'} = $node->findvalue('@desc');
}
# VENUE BUYER TYPES
foreach my $node ($DATA{'DOM'}->findnodes('//buyer_types/buyer_type')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'ID'} = $id;
$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'CODE'} = $node->findvalue('@code');
$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'DESC'} = uc($node->findvalue('@desc'));
# &substituteUmlauts(\$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'DESC'});
$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'DISPLAY_INDICATOR'} = uc($node->findvalue('@desc'));
# &substituteUmlauts(\$DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id}{'DISPLAY_INDICATOR'});
}
# MASTER CONFIG TO VENUE
$DATA{'COMPILED'}{'VENUE'}{'CAPACITY'} = $DATA{'DOM'}->findvalue('//master_config/@capacity');
# MASTER SECTION CONFIG
foreach my $node ($DATA{'DOM'}->findnodes('//master_config/section_config/section')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'ID'} = $id;
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'CODE'} = $node->findvalue('@code');
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'DESC'} = $node->findvalue('@desc');
}
# PRICE_STRUCTURE PRICESCALE
foreach my $node ($DATA{'DOM'}->findnodes('//price_structure/pricescale')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'CURRENCY'} = $node->findvalue('@currency');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'PRICES'}{'REF_PRICE'} = $node->findvalue('@ref_price');
# BUYER TYPES
foreach my $node_buyer ($node->findnodes('./buyer_type')) {
my $id2 = $node_buyer->findvalue('@id');
my $desc = $DATA{'COMPILED'}{'VENUE'}{'BUYER_TYPES'}{$id2}{'DESC'};
my $price = $node_buyer->findvalue('@price');
$DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id}{'PRICES'}{$desc} = $price;
}
}
# SEATMAP_CONFIG
foreach my $node ($DATA{'DOM'}->findnodes('//seatmap_config/seatmap')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'ID'} = $id;
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'CODE'} = $node->findvalue('@code');
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'DESC'} = $node->findvalue('@desc');
$DATA{'COMPILED'}{'VENUE'}{'SEATMAP_CONFIG'}{$id}{'HOTSPOT_COORDS'} = $node->findvalue('@hotspot_coords');
}
# MASTER SECTION INVENTORY
foreach my $node ($DATA{'DOM'}->findnodes('//master_config/section_inventory/section')) {
my $id = $node->findvalue('@id');
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'CAPACITY'} = $node->findvalue('@capacity');
# PRICESCALE
my $still_available = 0;
foreach my $node_pricescale ($node->findnodes('./pricescale')) {
my $id2 = $node_pricescale->findvalue('@id');
my $available = $node_pricescale->findvalue('@available');
$still_available += $available;
my $price = $DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id2}{'PRICES'}{'REF_PRICE'};
my $code = $DATA{'COMPILED'}{'VENUE'}{'PRICESCALES'}{$id2}{'CODE'};
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'AVAILABLILITY'}{$code}{'PRICE'} = $price;
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'AVAILABLILITY'}{$code}{'AVAILABLE'} = $available;
}
$DATA{'COMPILED'}{'VENUE'}{'SECTION_CONFIG'}{$id}{'STILL_AVAILABLE'} = $still_available;
}
}
sub loadXML {
&Delimiter((caller(0))[3]);
my ($xml, $DATA_ref) = @_;
# DELETE IF DOM ALREADY PRESENT
if (ref($$DATA_ref) eq 'XML::LibXML::Document') {
print 'DELETING EXISTING ' . ref($$DATA_ref) . "\n" if $CONFIG{'DEBUG'};
$$DATA_ref = ();
}
if (!$CONFIG{'ONLINE'}) {
print "LOADING $xml...\n" if $CONFIG{'DEBUG'};
$$DATA_ref = eval { XML::LibXML->load_xml(location => $xml) } or die "DIE: XML LOADING ERROR\n" . $@;
}
elsif ($CONFIG{'ONLINE'}) {
print "LOADING XML...\n" if $CONFIG{'DEBUG'};
$$DATA_ref = eval { XML::LibXML->load_xml(string => $xml) } or die "DIE: XML LOADING ERROR\n" . $@;
# $$DATA_ref = eval { decode('utf-8', encode('cp850', XML::LibXML->load_xml(string => $xml) ) ) } or die "DIE: XML LOADING ERROR\n" . $@;
}
}
sub getParameter {
&Delimiter((caller(0))[3]);
return if !$CONFIG{'ONLINE'};
my $url = $ENV{QUERY_STRING};
my $decoded = uri_decode($url);
say "decoded: " . $decoded if ($CONFIG{'DEBUG'});
my $uri = URI->new($decoded);
%{$DATA{'PARAMETER'}} = $uri->query_form;
#$DATA{'PARAMETER'}{'url'} = url_param('url');
$DATA{'PARAMETER'}{'url'} = $decoded;
$DATA{'PARAMETER'}{'url'} =~ s/^url=//;
# Remove note, request_switch from decoded uri
$DATA{'PARAMETER'}{'url'} =~ s/&note(=[^&]*)?|^note(=[^&]*)?&?//;
$DATA{'PARAMETER'}{'url'} =~ s/&request_switch(=[^&]*)?|^request_switch(=[^&]*)?&?//;
}
sub get {
&Delimiter((caller(0))[3]);
my $url = shift;
if ($CONFIG{'USE_CORSANYWHERE'}) {
say 'Generating url for cors-anywhere...';
my ($scheme, $auth, $path, $query, $frag) = uri_split($url);
#say "scheme: $scheme\nauth: $auth\npath: $path\nquery: $query\nfrag: $frag";
$url = 'https://cors.zinomedia.de/purchase.tickets.com:443' . $path . '?' . $query;
say "cors-anywhere URL: $url";
}
if ($CONFIG{'ONLINE'}) {
print "GET:\n$url\n" if $CONFIG{'DEBUG'};
#my $response = $ua->get($url);
my $response = $ua->get($url,
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language' => 'de,en-US;q=0.7,en;q=0.3',
'Host' => 'purchase.tickets.com',
);
print 'STATUS_LINE: ' . $response->status_line . "\n" if $CONFIG{'DEBUG'};
if ($response->is_success) {
return $response->decoded_content;
}
else {
$response->code();
$response->message();
$response->status_line();
say 'Get unsuccessful' if $CONFIG{'DEBUG'};
die;
}
}
elsif (!$CONFIG{'ONLINE'}) {
print "SET AS OFFLINE: USING LOCAL XML\n" if $CONFIG{'DEBUG'};
}
}
sub Delimiter {
my $SubName = shift;
print "\n" . "\n> SUB " . $SubName . "\n" . '-' x 80 . "\n" if $CONFIG{'DEBUG'};
#print "\n" . "-" x 80 . "\nSUB " . $SubName . "\n" . '-' x 80 . "\n";
}
exit;