#!/usr/bin/env perl
package Manager;
use threads;
use strict;
no warnings 'uninitialized';
use Mojolicious::Lite -signatures;
use Mojo::Promise;
use Mojo::UserAgent;
use Time::Local;
use Time::Piece;
use Time::Duration;
use Date::Parse;
use Clone qw(clone);
use feature 'signatures';
no warnings 'experimental::signatures';
use Mojolicious::Static;
use Mojo::Log;
use Mojo::Transaction::WebSocket;
use Mojo::Parameters;
use Mojo::DOM;
use Mojo::JSON qw(decode_json encode_json);
use URI::Encode qw(uri_encode uri_decode);
use List::Util qw(shuffle);
plugin 'RenderFile';
use Data::Dumper;
use Mojo::Util qw/md5_sum html_unescape term_escape quote unquote secure_compare url_escape url_unescape network_contains punycode_decode punycode_encode b64_decode b64_encode/;
use File::Find;
use File::Slurp;
use File::Type;
use File::Monitor;
use Number::Format qw/:subs/;
use SQL::Abstract;
use Mojo::SQLite;
use Mojo::IOLoop;
use Mojolicious::Sessions;
use Mojo::Server::Daemon;
use Mojolicious::Renderer;
use Crypt::Simple;
use HTML::Strip;
use HTML::Parser;
use Data::UUID;
use Storable;
use Math::Trig qw(cartesian_to_spherical spherical_to_cartesian great_circle_distance rad2deg deg2rad great_circle_bearing great_circle_direction great_circle_destination);
use MIME::Base64;
use Device::SerialPort qw( :PARAM :STAT 0.07 );
require "./Websocket.pl";
require "./subroutines.pl";
require "./Music.pl";
require "./hooks.pl";
my $tuuid = Data::UUID->new;
my $thread_uuid = $tuuid->create_str();
my $universal_splitter = $gb::universal_splitter;
our $database;
our $sql;
our $config_file = read_file('./config.json');
our $config = decode_json $config_file;
our $logfile = &subs::home($config->{'logfile'});
`touch $logfile` if not -e $logfile;
our $log = Mojo::Log->new(path => $logfile);
my $environment = $config->{'environment'};
our $random_caching_string = &subs::random_string_creator(10);
my $duty_file = &subs::home('~/.president/on_duty');
write_file($duty_file, &subs::rightNow());
$subs::database_holder->{'last_restart'} = &subs::rightNow();
my $main_process = $$;
my $device = &subs::device_setter();
my $user_agent = $gb::user_agent;
if ($device eq 'mobile' && `ps -e | grep sshd` eq '') {
`sshd`;
}
sub record_video($data) {
return if $device eq 'mobile';
my $app = $data->{'app'};
my $uuid = $data->{'uuid'};
my $timestamp = $data->{'timestamp'};
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'video_location', device => $device } ));
my $filename = $folder . '/' . $app;
`mkdir -p $filename` unless -e $filename;
$filename = $filename . '/' . $app . '_' . $timestamp . '.webm';
threads->create(sub() {
`ffmpeg -i /dev/video0 $filename`;
});
return [];
}
sub record_audio($data) {
my $app = $data->{'app'};
my $uuid = $data->{'uuid'};
my $timestamp = $data->{'timestamp'};
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'rec_location', device => $device } ));
my $filename = $folder . '/' . $app;
`mkdir -p $filename` unless -e $filename;
if ($device eq 'mobile') {
$filename = $filename . '/' . $app . '_' . $timestamp . '.mp3';
}
else {
$filename = $filename . '/' . $app . '_' . $timestamp . '.wav';
}
if ($device eq 'mobile') {
threads->create(sub() {
`termux-microphone-record -l 0 -e mp3 -f $filename`;
});
}
elsif ($device eq 'computer') {
threads->create(sub() {
`rec $filename`;
});
}
return [];
};
sub record_video_stop($data) {
return if $device eq 'mobile';
my $app = $data->{'app'};
my $uuid = $data->{'uuid'};
my $timestamp = $data->{'timestamp'};
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'video_location', device => $device } ));
my $filename = $folder . '/' . $app;
`mkdir -p $filename` unless -e $filename;
`pkill ffmpeg`;
my $stopped = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app })->hashes->[0];
if ($stopped->{'uuid'} && $stopped->{'type'} eq 'record') {
my $files = eval { return decode_json $stopped->{'file'} } || [];
$filename = $filename . '/' . $app . '_' . $timestamp . '.webm';
my $duration = $timestamp - $stopped->{'timestamp'};
my $data = { server_time => &subs::rightNow(), f => $filename, uuid => &subs::random_string_creator(16), type => 'video' };
$data = &thumbnail_creator($data);
push @{$files}, $data;
my $jdata = encode_json $files;
&subs::db_update('appointments', {
server_time => &subs::rightNow(),
duration => $duration,
encryption_standard => undef,
file => $jdata,
type => 'video',
stop_timestamp => &subs::rightNow(),
stop_seen => 'yes',
seen => 'yes'
},
{
app => $app,
uuid => $uuid
});
sleep 2;
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
&subs::file_encrypter({ app => $app });
}
return $filename;
}
sub record_audio_stop($data) {
my $c = $data->{'c'};
my $app = $data->{'app'};
my $timestamp = $data->{'timestamp'};
my $uuid = $data->{'uuid'};
my $filename;
if ($device eq 'mobile') {
`termux-microphone-record -q`;
}
elsif ($device eq 'computer') {
`pkill rec`;
}
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'rec_location', device => $device } ));
my ($db) = &subs::database_grabber();
my $stopped = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app })->hashes->[0];
if ($stopped->{'uuid'} && $stopped->{'type'} eq 'record') {
$filename = $folder . '/' . $app;
`mkdir -p $filename` unless -e $filename;
if ($device eq 'mobile') {
$filename = $filename . '/' . $app . '_' . $timestamp . '.mp3';
}
else {
$filename = $filename . '/' . $app . '_' . $timestamp . '.wav';
}
my $duration = $timestamp - $stopped->{'timestamp'};
my $files = eval { return decode_json $stopped->{'file'} } || [];
my $data = { server_time => &subs::rightNow(), f => $filename, uuid => &subs::random_string_creator(16), type => 'audio' };
push @{$files}, $data;
my $jdata = encode_json $files;
&subs::db_update('appointments', {
server_time => &subs::rightNow(),
duration => $duration,
encryption_standard => undef,
file => $jdata,
type => 'audio',
stop_timestamp => &subs::rightNow(),
stop_seen => 'yes',
seen => 'yes'
},
{
app => $app,
uuid => $uuid
});
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
&subs::file_encrypter({ app => $app });
}
return $filename;
}
sub timestamp_adjuster($c) {
my $timestamp = $c->param('timestamp');
my $time_machine = $c->param('time_machine');
my $timeshift = $c->param('timeshift');
my $ago = $c->param('ago');
if ($time_machine) {
$timestamp = &subs::ago_calc($time_machine,$timestamp);
}
if ($timeshift) {
if ($timeshift =~ /[0-9]/gi) {
$timestamp = &subs::ago_calc($timeshift,$timestamp);
}
}
if ($ago) {
$timestamp = &subs::ago_calc($ago,$timestamp);
}
return $timestamp;
}
post '/manager/take_picture' => sub($c) {
my $timestamp = ×tamp_adjuster($c);
my $camera = $c->param('camera');
my $app = $c->param('app');
my $uuid = $c->param('uuid');
my ($file,$ocr);
my $data = {
app => $app,
timestamp => $timestamp,
camera => $camera,
uuid => $uuid,
duty => 'image',
duuid => &subs::random_string_creator()
};
if ($timestamp >= &subs::rightNow() + 1000) {
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $uuid })->hashes->[0];
my $duties = eval { return decode_json $appt->{'duties'} } || [];
push @{$duties}, $data;
@{$duties} = sort { $a->{'timestamp'} <=> $b->{'timestamp'} } @{$duties};
my $next_duty = $duties->[0]->{'timestamp'};
my $jduties = encode_json $duties;
&subs::db_update('appointments', { duties => $jduties, next_duty => $next_duty, server_time => &subs::rightNow() }, { app => $app, uuid => $uuid });
}
else {
($file,$ocr) = &take_picture($c,$data);
}
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
$c->render(json => { files => $file, ocr => $ocr });
};
sub take_picture($c,$data) {
my $uuid = $data->{'uuid'} || undef;
my $timestamp = $data->{'timestamp'} || &subs::rightNow();
my $server_time = &subs::rightNow();
my $app = &subs::unformat_name($data->{'app'} || $c->param('app'));
unless ($c->session('suds')) {
$c->session('suds' => &subs::suds_grabber());
$c->stash('app' => $app);
$c->stash('uuid' => $uuid);
}
if (!grep { $_ eq $data->{'camera'} } @{$gb::capabilities->{&subs::device_setter()}->{'camera'}}) {
&remote_relay_request($c);
return ('denial','denial');
}
my $camera = $data->{'camera'} || 0;
my $warranty = &subs::ago_calc(&subs::setting_grabber({ app => 'app', setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' }), $server_time);
my ($filename,$ocr);
my ($db,$database,$sql) = &subs::database_grabber();
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'photo_location', device => $device } ));
$filename = $folder . '/' . $app;
my $resolution = &subs::setting_grabber({ app => 'misc', setting => 'photo_size' } ) || '1920x1080';
`mkdir -p $filename` unless -e $filename;
my $thumb = $filename . '/thumbs/';
`mkdir -p $thumb` unless -e $thumb;
$thumb = $thumb . $app . '_' . $timestamp . '.jpg';
$filename = $filename . '/' . $app . '_' . $timestamp;
my $text_file = $filename;
$filename = $filename . '.jpg';
if ($device eq 'mobile' && ($camera eq 0 || $camera == 1)) {
`termux-camera-photo -c $camera $filename`;
}
elsif ($device eq 'computer' && $camera eq 'webcam') {
eval { `ffmpeg -i /dev/video0 $filename` };
}
if (-e $filename) {
$ocr = &ocr_reader($c,$filename);
`magick $filename -resize $resolution $filename` unless lc $resolution eq 'raw';
}
my $duration = $server_time - &subs::rightNow();
my $u_data = { thumb => $thumb, server_time => &subs::rightNow(), f => $filename, uuid => &subs::random_string_creator(9), type => 'image', ocr => $ocr };
$u_data = &thumbnail_creator($u_data);
my $files = [$u_data];
if ($uuid) {
my $appt = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app })->hashes->[0];
my $pre_files = eval { return decode_json $appt->{'file'} } || [];
push @{$files}, @{$pre_files};
my $jfiles = encode_json $files;
&subs::db_update('appointments', { encryption_standard => undef, duration => $duration, file => $jfiles, server_time => &subs::rightNow() }, { app => $app, uuid => $uuid });
}
else {
$uuid = &subs::random_string_creator(20);
my $jfiles = encode_json $files;
&appointment_writer($c, {
app => $app,
type => 'image',
file => $jfiles,
timestamp => $timestamp,
server_time => $server_time,
uuid => $uuid,
warranty => $warranty,
duration => $duration
});
}
my $jfiles = encode_json $files;
&subs::file_encrypter({ app => $app });
return ($jfiles,$ocr);
}
post '/manager/scan_document' => sub($c) {
my $timestamp = ×tamp_adjuster($c);
my $feed = $c->param('feed');
my $app = $c->param('app');
my $uuid = $c->param('uuid');
my $scandata = {
timestamp => $timestamp,
feed => $feed,
uuid => $uuid,
app => $app,
source => 'existing',
duty => 'scan',
duuid => &subs::random_string_creator()
};
my $file;
if ($timestamp >= &subs::righNow() + 1000) {
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $uuid })->hashes->[0];
my $duties = eval { return decode_json $appt->{'duties'} } || [];
push @{$duties}, $scandata;
@{$duties} = sort { $a->{'timestamp'} <=> $b->{'timestamp'} } @{$duties};
my $next_duty = $duties->[0]->{'timestamp'};
my $jduties = encode_json $duties;
&subs::db_update('appointments', { duties => $jduties, next_duty => $next_duty, server_time => &subs::rightNow() }, { app => $app, uuid => $uuid });
}
else {
$file = &scan($c, $scandata);
}
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
$c->render(json => { files => $file });
};
sub scan($c,$scandata) {
my $timestamp = $scandata->{'timestamp'};
my $feed = $scandata->{'feed'};
my $uuid = $scandata->{'uuid'};
my $suds = $c->session('suds') || &subs::suds_grabber();
$c->session('suds' => $suds);
my $source = $scandata->{'source'};
my $app = $scandata->{'app'} || $c->param('app');
if (!grep { $_ eq $scandata->{'feed'} } @{$gb::capabilities->{&subs::device_setter()}->{'scan'}}) {
&remote_relay_request($c);
return 'denial';
}
my ($db,$database,$sql) = &subs::database_grabber();
my $start_time = &subs::rightNow();
my $folder = &subs::home(&subs::setting_grabber( { app => 'misc', setting => 'scan_location', device => $device } ));
my $filename = $folder . '/' . $app;
$filename = &subs::home($filename);
`mkdir -p $filename` unless -e $filename;
my $thumb_folder = $filename . '/thumbs';
`mkdir -p $thumb_folder` unless -e $thumb_folder;
my $thumb = $thumb_folder . '/' . $app . '_' . $timestamp . '.jpg';
my $file = $filename . '/' . $app . '_' . $timestamp;
my $image_file = $file . '.jpg';
my $printer = &subs::device_lister($timestamp,'printer');
Mojo::IOLoop->subprocess->run_p(sub {
my $command;
($db,$database,$sql) = &subs::database_grabber();
my $scanner = $config->{'scanners'}->[0];
my $address = ("hpaio:/net/officejet_3830_series?ip=" . $printer->{'ip'}) || $scanner-{'address'};
my $resolution = $scanner->{'resolution'};
if ($feed eq 'flatbed' && grep { lc $_ eq 'flatbed' } @{$scanner->{'feeds'}}) {
$command = "scanimage --format tiff --source Flatbed --batch=$file.tiff --mode Color -d $address --resolution=$resolution;";
}
elsif ($feed eq 'adf' && grep { lc $_ eq 'adf' } @{$scanner->{'feeds'}}) {
$command = "scanimage --format tiff --source ADF --batch=$file\_\%d.tiff --mode Color -d $address --resolution=$resolution;";
}
my $caseworker = `$command`;
my $scans = `ls -tr $file*.tiff`;
sleep 1;
my @scans = split "\n",$scans;
my @filenames;
my $count = 1;
my $photo_size = &subs::setting_grabber({ app => 'misc', setting => 'scan_size', device => $device } ) || '1920x1080';
foreach my $scan (@scans) {
$file = $scan;
$file =~ s/\.[^.]+$//;
$image_file = $file . '.jpg';
my @image_file = split /\//, $image_file;
my $thumb_file = pop @image_file;
$thumb = $thumb_folder . '/' . $thumb_file;
my $ocr = &ocr_reader($c,$scan);
if ($photo_size ne "Raw") {
my $convert = `magick convert $scan -resize $photo_size $image_file`;
}
else {
my $convert = `magick convert $scan $image_file`;
}
`shred -u $scan`;
push @filenames, { f => $image_file , thumb => $thumb, ocr => $ocr};
$count++;
}
my $fnames = [];
foreach my $f ( @filenames ) {
my $file_data = { server_time => &subs::rightNow(), ocr => $f->{'ocr'}, f => $f->{'f'}, thumb => $f->{'thumb'}, uuid => &subs::random_string_creator(10), type => 'document', 'of' => $f->{'f'} };
$file_data = &thumbnail_creator($file_data);
push @{$fnames}, $file_data;
}
if ($uuid) {
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $uuid })->hashes->[0];
my $pre_files = eval { return decode_json $appt->{'file'} } || [];
if (scalar @{$pre_files} > 0) {
push @{$fnames}, @{$pre_files};
}
}
my $filenames = encode_json $fnames;
my $server_time = &subs::rightNow();
my $duration = ($start_time - $server_time );
if (@{$fnames} > 0) {
&subs::db_query('update appointments set server_time = ?, duration = ?, file = ?, encryption_standard = ? where app = ? and uuid = ?',
&subs::rightNow(),$duration, $filenames, undef, $app, $uuid );
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
}
elsif ( scalar @filenames == 0 && $source ne 'existing' ) {
&subs::db_delete('appointments', { uuid => $uuid });
&Websocket::send('server', { console => '$(\'appointment_detail[app="' . $app . '"][uuid="' . $uuid . '"]\').remove();'});
}
&subs::file_encrypter({ app => $app });
});
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
return encode_json [{ f => $image_file }];
}
sub ocr_reader($c,$filename) {
my $text_file = $filename;
`tesseract $filename $text_file`;
$text_file = $text_file . '.txt';
my $ocr = read_file($text_file);
$ocr =~ s/[^\x00-\x7F]+//gi;
$ocr = &subs::note_encrypter($c->session('suds'),$ocr);
`shred -u $text_file`;
return $ocr;
}
sub play_audio($file) {
threads->create(sub() {
$file = &subs::terminal_name($file);
if ( `ps -e | grep play` ) {
`pkill play`;
}
else {
Mojo::IOLoop->subprocess->run_p(sub {
`play "$file"`;
});
}
});
return $file;
}
sub play_audio_stop($file) {
`pkill play`;
return $file;
}
get '/file_open' => sub($c) {
my $data = &rock_and_roll($c);
# $c->render(text => 'no') if $data eq 'no';
};
sub rock_and_roll($c) {
my $man = 'rejected';
my $file = $c->param('file');
if ($c->param('remote_uuid') && $c->param('remoted') ne 'yes') {
$c->param('subprocess' => 'yes');
my $result = &remote_relay_request($c);
$c->render(data => $result);
return;
}
my ($db,$database,$sql) = &subs::database_grabber();
my $mag;
unless ( $c->session('authentication') eq 'approved' ) {
my $uuid = $c->param('uuid');
my $fq = &subs::db_query('select * from magazine where uuid = ?',$uuid );
$mag = $fq->hashes->[0];
if ($mag->{'status'} eq 'publish') {
my $public = &subs::setting_grabber({ app => &subs::unformat_name($mag->{'title'}), setting => 'public' });
if ($public eq 'on' && $mag-{'content'} =~ /$file/) {
$man = 'approved';
}
}
}
else {
$man = &authentication_passer($c);
}
if ($man eq 'approved') {
my $tdir = &subs::home('~/.president');
if ($device ne 'mobile') {
$tdir = '/tmp';
}
$file = uri_decode $c->param('track') unless $file;
my $timestamp = $c->param('timestamp') || &subs::rightNow();
my $filename = $file;
# return 'no' unless -e &subs::terminal_name($file);
if ($c->param('as_is') && -e $file) {
my $data = read_file($file);
$data = encode_base64 $data;
$c->render(data => $data);
return;
}
elsif ($c->param('as_is')) {
$c->render(text => 'not found');
return;
}
my $app = &subs::unformat_name($c->param('app'));
my $writer = {
timestamp => $timestamp,
app => &subs::unformat_name($mag->{'title'}) || $app,
file => $file,
uuid => $mag->{'uuid'},
type => 'file'
};
my @file_split = split /\//, $file;
my $file_match = $file_split[-1];
my $appt_q;
if ($c->param('app_uuid')) {
$appt_q = &subs::db_query('select * from appointments where uuid=? and app=? LIMIT 1',$c->param('app_uuid'), $app);
}
else {
$appt_q = &subs::db_query('select * from appointments where file like ? and app=? and (server_time=? or timestamp=?) LIMIT 1','%' . $file_match . '%', $app,$timestamp,$timestamp);
}
my $appter = $appt_q->hashes;
my $appt_server_time = $appter->[0]->{'server_time'};
my $atf = eval { return decode_json $appter->[0]->{'file'} } || [];
my $file_data = {};
my $thumbnail_size = &subs::setting_grabber({ app => 'misc', setting => 'thumbnail_size' }) || 'none';
foreach my $af ( @{$atf} ) {
if ($file eq $af->{'f'}) {
$appt_server_time = $af->{'server_time'};
$file_data = $af;
if ($af->{'thumb'} && $c->param('thumb') && $thumbnail_size ne 'none') {
if (-e $af->{'thumb'}) {
$file = $af->{'thumb'};
$c->param('thumb' => undef);
}
}
}
}
if ($file =~ /\.enc$/gi) {
my $encryption_standard = $appter->[0]->{'encryption_standard'} || &subs::setting_grabber({ app => 'misc', setting => 'encryption_standard' }) || "aes-256-ctr";
my @encryption_standards = ( $encryption_standard );
if (!$appter->[0]->{'uuid'}) {
my @file_splitter = split /\//, $file;
$appt_q = &subs::db_query('select * from appointments where app = ? and file is not null and file like ?',$app,'%' . $file_splitter[-1] . '%' );
my $apptser = $appt_q->hashes;
my $appt_server_time = $apptser->[0]->{'server_time'};
foreach my $at ( @{$apptser} ) {
if ( $at->{'encryption_standard'} ne $encryption_standard ) {
push @encryption_standards, $at->{'encryption_standard'};
}
my $atf = eval { return decode_json $at->{'file'} } || [];
foreach my $af ( @{$atf} ) {
if ($file eq $af->{'file'}) {
$appt_server_time = $af->{'server_time'};
$file_data = $af;
if ($af->{'thumb'} && $c->param('thumb') && $thumbnail_size ne 'none') {
if (-e $af->{'thumb'}) {
$file = $af->{'thumb'};
$c->param('thumb' => undef);
}
}
}
}
}
}
unless ($appt_server_time) {
if (-e $file) {
my @stat = stat($file);
$appt_server_time = $stat[10] * 1000;
}
}
my $suds = $c->session('suds');
my $passwords = &subs::db_query('select * from security where level != ? and timestamp <= ? order by timestamp DESC','padlock',$appt_server_time);
my $pwords = $passwords->hashes;
foreach my $p ( @{$pwords} ) {
my $secret = &subs::decrypter($suds, $p->{'credential'}, $appt_server_time);
my $filename = $file;
$filename =~ s/\.enc$//gi;
foreach my $es ( @encryption_standards ) {
my $data = `openssl enc -d -k "$secret" -$encryption_standard -pbkdf2 -in $file`;
my $ft = File::Type->new();
my $fd = $ft->checktype_contents($data);
if ($fd ne 'application/octet-stream' || ($file =~ /webm/)) {
my @ext = split /\./, $file;
my $ext = $ext[-2];
if ($c->param('duty')) {
return {
data => $data,
image => 'data:' . $fd . ';base64,' . encode_base64($data,''),
fd => $fd,
timestamp => $appt_server_time,
ext => $ext
};
}
elsif ($fd =~ /pdf/) {
$c->render(format => 'pdf', data => $data);
return;
}
else {
if ($c->param('thumb') eq 'ya') {
my @filename = split /\./, $file;
my $ext = $filename[-2];
unless ( -e $file_data->{'thumb'}) {
my $filename = $tdir . '/' .&subs::random_string_creator(20) . '.' . $ext;
if ($file =~ /webm/) { $fd = 'video/webm'; }
my $command = 'openssl enc -d -k "' . $secret . '" -' . $encryption_standard . ' -pbkdf2 -in ' . $file .' -out ' . $filename;
`$command`;
if ($file_data->{'type'} eq 'video' || grep { $_ eq $ext } qw/mp4 webm/ ) {
my $command2 = 'ffmpeg -ss 00:00:00.010 -f ' . $ext . ' -i ' . $filename . ' -vframes 1 -c:v png -f image2pipe - | magick - -resize ' . $thumbnail_size . ' - ';
$file_data->{'type'} = 'video';
$data = `$command2`;
}
elsif ($file_data->{'type'} eq 'image' || grep { $_ eq $ext } qw/bmp tiff jpg png/) {
my $command2 = 'magick ' . $filename . ' -resize ' . $thumbnail_size . ' -';
$file_data->{'type'} = 'image';
$data = `$command2`;
}
if ($file_data->{'uuid'} && $data && $thumbnail_size ne 'none') {
pop @file_split;
my $folder = join '/', @file_split;
$folder = $folder . '/thumbs';
`mkdir -p $folder`;
my $worker_id = &subs::random_string_creator(10);
my $priority = $folder . '/priority.txt';
my $pr = eval { return decode_json read_file($priority) } || {};
until ($pr->{$appter->[0]->{'uuid'}}->{'state'} ne 'working' || $pr->{$appter->[0]->{'uuid'}}->{'time'} < &subs::rightNow() - 6000) {
sleep .5;
$pr = eval { return decode_json read_file($priority) } || {};
}
$pr->{$appter->[0]->{'uuid'}}->{'state'} = 'working';
$pr->{$appter->[0]->{'uuid'}}->{'time'} = &subs::rightNow();
$pr->{$appter->[0]->{'uuid'}}->{'worker'} = $worker_id;
my $jpr = encode_json $pr;
write_file($priority, $jpr);
my $path = $folder . '/' . &subs::random_string_creator(23) . '.png.enc';
$file_data->{'thumb'} = $path;
$file_data->{'server_time'} = &subs::rightNow();
$file_data = &subs::file_media_information($file_data,$filename);
write_file($filename, $data);
my $encrypt = `openssl enc -e -k "$secret" -$encryption_standard -pbkdf2 -in $filename -out $path`;
my $appt = &subs::db_select('appointments', undef, { uuid => $appter->[0]->{'uuid'}, app => $appter->[0]->{'app'} })->hashes->[0];
$atf = eval { return decode_json $appt->{'file'} } || [];
my @natf = grep { $_->{'uuid'} eq $file_data->{'uuid'} } @{$atf};
if (-e $natf[0]->{'thumb'}) { my $natfthumb = $natf[0]->{'thumb'}; `shred -u $natfthumb`; }
@{$atf} = grep { $_->{'uuid'} ne $file_data->{'uuid'} } @{$atf};
push @{$atf}, $file_data;
my $jdata = encode_json $atf;
&subs::db_update('appointments', { server_time => &subs::rightNow(), file => $jdata }, { uuid => $appter->[0]->{'uuid'}, app => $appter->[0]->{'app'} });
my $pr = eval { return decode_json read_file($priority) } || {};
delete $pr->{$appter->[0]->{'uuid'}};
if (scalar keys %{$pr} == 0) {`shred -u $priority`; }
else {
$jpr = encode_json $pr;
write_file($priority, $jpr);
}
}
Mojo::IOLoop->subprocess->run_p(sub {
`shred -u $filename`;
});
}
}
$c->render_file(data => $data);
return;
}
}
last;
}
}
}
elsif ($c->param('duty')) {
my $data = read_file($file);
my $ft = File::Type->new();
my $fd = $ft->checktype_contents($data);
my @ext = split /\./, $file;
my $ext = $ext[-1];
my $server_time;
if (-e $file) {
my @stat = stat($file);
$server_time = $stat[10] * 1000;
}
return {
data => $data,
image => 'data:' . $fd . ';base64,' . encode_base64($data,''),
fd => $fd,
timestamp => $server_time,
ext => $ext
};
}
elsif ($device eq 'mobile') {
if (-e $file) {
if ($c->param('thumb')) {
my $data;
if ($file_data->{'uuid'} && ! -e $file_data->{'thumb'} && $thumbnail_size ne 'none') {
my ($destination,$asset,$type) = &subs::file_device_renamer({ file => $file, app => $appter->[0]->{'app'}, type => $file_data->{'type'}, is_thumb => 1 });
$file_data->{'type'} = $type;
$file_data->{'thumb'} = $destination . $asset;
$file_data = &thumbnail_creator($file_data);
$data = read_file($file_data->{'thumb'});
$c->render(data => $data);
}
else {
my $filename = $tdir . '/' . &subs::random_string_creator(20) . '.png';
my $command = 'ffmpeg -ss 00:01:30.010 -i ' . &subs::terminal_name($file) . ' -vframes 1 -c:v png -f image2pipe - | magick - -resize 200x200 -';
my $data = `$command`;
$c->render_file(data => $data);
}
}
else {
my $sdata = read_file($file);
$c->render_file('data' => $sdata);
}
}
}
else {
if (-e $file) {
if ($c->param('thumb')) {
my $data;
if ($file_data->{'uuid'} && ! -e $file_data->{'thumb'} && $thumbnail_size ne 'none') {
my ($destination,$asset,$type) = &subs::file_device_renamer({ file => $file, app => $appter->[0]->{'app'}, type => $file_data->{'type'}, is_thumb => 1 });
$file_data->{'type'} = $type;
$file_data->{'thumb'} = $destination . $asset;
$file_data = &thumbnail_creator($file_data);
$data = read_file($file_data->{'thumb'});
$c->render(data => $data);
}
else {
my $filename = $tdir . '/' . &subs::random_string_creator(20) . '.png';
my $duration = $c->param('duration');
my @folder = split /\//, $file;
my $tfile = pop @folder;
my $folder = join '/', @folder;
my $thumb_folder = $folder . '/thumbs';
my $tfd = &subs::terminal_name($thumb_folder);
`mkdir -p $tfd` unless -e $thumb_folder;
my @tfile = split /\./, $tfile;
pop @tfile;
if ($c->param('chapter') eq 'ya') {
$tfile = (join '.', @tfile) . ' ' . $c->param('id') . '.png';
if ($c->param('end_time')) {
$duration = (($c->param('end_time') - $c->param('start_time')) / 2 + $c->param('start_time'));
}
else {
$duration = $c->param('start_time') + 5;
}
}
else {
$tfile = (join '.', @tfile) . '.png';
}
$tfile = $thumb_folder . '/' . $tfile;
if ( -e $tfile && !$c->param('position')) {
$data = read_file($tfile);
}
else {
my $save = 1;
if ($c->param('position')) {
$duration = $c->param('position');
$save = 0;
}
elsif ($c->param('chapter') ne 'ya') {
if ($duration < 10) {
$duration = '00:00:01.000';
}
elsif ($duration < 60) {
$duration = '00:00:12.000';
}
elsif ($duration < 120) {
$duration = '00:01:01.000';
}
else {
$duration = '00:02:00.020';
}
}
my $command = 'ffmpeg -ss ' . $duration . ' -i ' . &subs::terminal_name($file) . ' -vframes 1 -c:v png -f image2pipe - | magick - -resize 200x200 -';
$data = `$command`;
write_file($tfile, $data) if $save == 1;
}
}
$c->render_file(data => $data);
}
else {
$c->render_file('filepath' => $file);
}
}
else {
$c->render('text' => '');
}
}
}
else {
$c->render('text' => 'no');
}
}
sub appointment_writer($c,$app) {
# &subs::cache_delete({ app => $app->{'app'}, context => 'template' });
$app->{'server_time'} = $app->{'server_time'} || &subs::rightNow();
$app->{'timestamp'} = $app->{'server_time'} unless $app->{'timestamp'};
$app->{'browser_tab_id'} = $c->param('browser_tab_id') if $c->param('browser_tab_id') && !$app->{'browser_tab_id'};
my $remote_address = $app->{'remote_address'};
delete $app->{'remote_address'};
my $timestamp = $app->{'timestamp'};
my $server_time = $app->{'server_time'};
$app->{'device'} = $device;
$app->{'uuid'} = $app->{'uuid'} || &subs::random_string_creator(90);
if ($app->{'timestamp'} <= $app->{'server_time'} + 1000) {
$app->{'seen'} = 'yes';
}
my ($db,$database,$sql) = &subs::database_grabber();
my $init = &subs::setting_initializer($app->{'app'},$app->{'timestamp'});
$app->{'app'} = $init->{'app'};
($app->{'app'},undef) = &subs::typesetter($app->{'app'});
my $settings = &subs::settings_grabber({ app => $app->{'app'} });
if ($app->{'type'} eq 'usual' || $app->{'type'} eq 'start' || $app->{'type'} eq 'record') {
my ($model,$options);
($model,$options,$app->{'model'},$app->{'options'}) = &subs::usual_appointment_maker($app,$settings);
if ($model->{'unit'} && !$app->{'unit'}) {
$app->{'unit'} = $model->{'unit'};
}
if ($model->{'quantity'} && !$app->{'quantity'}) {
$app->{'quantity'} = $model->{'quantity'};
}
}
my $warranty_holder = $app->{'timestamp'} > $app->{'server_time'} ? $app->{'timestamp'} : $app->{'server_time'};
$app->{'warranty'} = $app->{'warranty'} || &subs::ago_calc($init->{'warranty'},$warranty_holder);
$app->{'project'} = $settings->{'t_project'} unless $app->{'project'};
$app->{'pos'} = $settings->{'pos'} unless $app->{'pos'};
if ($app->{'type'} eq 'record') {
my $recording_type = &subs::setting_grabber({ app => $app->{'app'}, setting => 'record' });
my $dat = { recorder => $recording_type };
if ($recording_type eq 'video') {
$app->{'seen'} = undef;
# $dat->{'camera'} = $camera;
}
elsif ($recording_type eq 'audio') {
$app->{'seen'} = undef;
}
elsif ($recording_type eq 'screen') {
$app->{'seen'} = undef;
}
elsif ($recording_type eq 'security') {
&record_video({ app => $app->{'app'}, uuid => $app->{'uuid'}, timestamp => $app->{'timestamp'} }) if $app->{'seen'} eq 'yes';
}
else {
&record_audio({ app => $app->{'app'}, uuid => $app->{'uuid'}, timestamp => $app->{'timestamp'} }) if $app->{'seen'} eq 'yes';
}
$app->{'data'} = encode_json $dat;
}
if ($app->{'uuid'} && 0) {
my $pa = &subs::db_query('select * from appointments where uuid=?', $app->{'uuid'});
my $prev = $pa->hashes->[0];
if ($prev->{'app'}) {
my $duration = ($prev->{'duration'} + (&subs::rightNow() - $prev->{'timestamp'}));
&subs::db_query('update appointments set duration=?, timestamp=? where uuid=?', $duration, $app->{'timestamp'}, $app->{'uuid'});
}
else {
&subs::db_insert('appointments', $app);
}
}
if ($app->{'type'} eq 'stop') {
my $appts = &subs::db_query('select * from appointments where app=? and (type=? or type = ? ) and timestamp < ? order by timestamp asc', $app->{'app'},'start','record',$app->{'timestamp'})->hashes;
return {} unless scalar @{$appts} > 0;
foreach my $appt ( @{$appts} ) {
$app->{'type'} = 'stop';
$app->{'duration'} = $appt->{'timestamp'} - $app->{'timestamp'};
$app->{'uuid'} = $appt->{'uuid'};
my $recording_type = &subs::setting_grabber({ app => $app->{'app'}, setting => 'record' }) || 'system';
if ($appt->{'type'} eq 'record') {
my $dat = eval { return decode_json $appt->{'data'} } || {};
if ($dat->{'recorder'} eq 'security') {
if ($app->{'seen'} eq 'yes') {
&record_video_stop({ app => $app->{'app'}, timestamp => $appt->{'timestamp'}, uuid => $appt->{'uuid'} }) if $appt->{'uuid'};
next;
}
else { $app->{'type'} = 'record'; };
}
elsif ($dat->{'recorder'} eq 'system') {
if ($app->{'seen'} eq 'yes') {
&record_audio_stop({ app => $appt->{'app'}, timestamp => $appt->{'timestamp'}, uuid => $appt->{'uuid'} }) if $appt->{'uuid'};
next;
}
else { $a->{'type'} = 'record'; };
}
else {
&Websocket::send('music', { console => 'jpStop(\'' . $appt->{'app'} . '\',\'' . $dat->{'recorder'} . '\',\'' . $appt->{'uuid'} . '\');' });
}
}
&subs::intelligent_automation_toggle({ appt_uuid => $app->{'uuid'}, app => $app->{'app'}, 'state' => 'off', timestamp => $app->{'timestamp'}, remote_address => $remote_address });
my $sources = &subs::db_select('appointments', undef, { source_uuid => $app->{'uuid'} })->hashes;
my $options = eval { return decode_json $appt->{'options'} } || [];
my $model = eval { return decode_json $appt->{'model'} } || {};
push @{$options}, $model if $model->{'uuid'};
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'start' ) {
my $dur = $so->{'timestamp'} - $timestamp;
my @current_option = grep { $_->{'name'} eq $so->{'app'} } @{$options};
my $co = $current_option[0];
my $so_data = {
duration => $dur,
server_time => $server_time,
};
my $ts = $timestamp;
if ($co->{'delay_stop'}) {
my $t = &subs::time_abbrev_translator($co->{'delay_stop'});
$ts = $ts + $t;
$dur = $dur + $t;
$so_data->{'duration'} = $dur;
$so_data->{'stop_timestamp'} = $ts;
}
my $so_data = { stop_timestamp => $ts, duration => $dur, server_time => $server_time };
if ($ts <= &subs::rightNow()) {
$so_data->{'type'} = $app->{'type'};
$so_data->{'stop_seen'} = 'yes';
$so_data->{'stop_timestamp'} = $app->{'timestamp'}
}
&subs::db_update('appointments', $so_data, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&subs::intelligent_automation_toggle({ appt_uuid => $so->{'uuid'}, app => $so->{'app'}, 'state' => 'off', timestamp => $ts, remote_address => $remote_address });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
&subs::db_update('appointments', { stop_timestamp => $app->{'timestamp'}, stop_seen => 'yes', duration => $app->{'duration'}, type => $app->{'type'}, server_time => &subs::rightNow() }, { uuid => $appt->{'uuid'}, app => $app->{'app'} });
}
}
else {
if ($app->{'type'} eq 'start' || $app->{'type'} eq 'record') {
&subs::intelligent_automation_toggle({ appt_uuid => $app->{'uuid'}, app => $app->{'app'}, 'state' => 'on', timestamp => $app->{'timestamp'}, remote_address => $remote_address });
if ($app->{'stop_timestamp'}) {
&subs::intelligent_automation_toggle({ appt_uuid => $app->{'uuid'}, app => $app->{'app'}, 'state' => 'off', timestamp => $app->{'stop_timestamp'}, remote_address => $remote_address });
}
if ($app->{'type'} eq 'record') {
my $jdata;
my $recording_type = &subs::setting_grabber({ app => $app->{'app'}, setting => 'record' }) || 'system';
my $dat = { recorder => $recording_type };
if ($recording_type eq 'video') {
$app->{'seen'} = undef;
#$dat->{'camera'} = $camera;
}
elsif ($recording_type eq 'audio') {
$app->{'seen'} = undef;
}
elsif ($recording_type eq 'screen') {
$app->{'seen'} = undef;
}
elsif ($recording_type eq 'video_front') {
# $dat->{'camera'} = $camera;
}
elsif ($recording_type eq 'security') {
&record_video({ app => $app->{'app'}, uuid => $app->{'uuid'}, timestamp => $app->{'timestamp'} }) if $app->{'seen'} eq 'yes';
}
else {
&record_audio({ app => $app->{'app'}, uuid => $app->{'uuid'}, timestamp => $app->{'timestamp'} }) if $app->{'seen'} eq 'yes';
}
$app->{'data'} = encode_json $dat;
}
}
&subs::db_insert('appointments', $app);
}
&Websocket::send('tab', { console => 'appointmentDetailGrabber("' . $app->{'app'} . '","' . $app->{'uuid'} .'");' });
&subs::appt_header_printer({ app => $app->{'app'} });
&budget_runner($app->{'app'});
if (1 == 0 && $app->{'app'}) {
# unless ( &subs::db_select('appointments', ['uuid'], { uuid => $uuid })->hashes > 0) {
my $params = Mojo::Parameters->new(%{$app});
$params = $params->to_string;
Mojo::IOLoop->subprocess->run_p(sub {
my $remote_machines = &subs::db_query('select * from remote_machines where connection=?', 'active')->hashes;
foreach my $rm ( @{$remote_machines} ) {
$rm = &remote_useragent_maker({ ip => $rm->{'ip'}, signatorial => $rm->{'signatorial'}, rm => $rm });
my $url = $rm->{'manager'} . '/manager/appointment/writer?' . $params;
my $res = $rm->{'ua'}->post($url);
my $additions = eval { return decode_json $rm->{'additions'} } || [];
# push @{$additions}, { app => $app, uuid => $app->{'uuid'}, scope => 'single', initialization => &subs::rightNow() };
my $jadditions = encode_json $additions;
&subs::db_update('remote_machines', { additions => $jadditions }, { uuid => $rm->{'uuid'}, signatorial => $rm->{'signatorial'} });
}
});
# }
}
return $app;
}
post '/manager/appointment/writer' => sub ($c) {
my $parameters = $c->req->body_params->{'string'};
my $params = Mojo::Parameters->new($parameters);
&appointment_writer($c,$params);
$c->render(json => $params);
};
my (@appointments,@results);
get '/' => sub ($c) {
my $homepage = &homepage_maker($c);
$c->render('text' => $homepage);
};
get '/manager/home' => sub($c) {
my $timestamp = $c->param('timestamp');
my $homepage = &homepage_maker($c);
$homepage = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'home', contents => $homepage }, $timestamp);
$c->render('text' => $homepage);
};
sub homepage_maker($c) {
my ($db,$database,$sql) = &subs::database_grabber();
unless ($database) {
$c->render(template => 'guest_layouts/denial');
}
my $articulation;
my $port = $c->req->url->base->port;
my $server_time = &subs::rightNow();
my $name = &subs::setting_grabber({ app => 'me', setting => 'my_name' }) || 'Home';
$articulation = &subs::db_query('select * from magazine where status=? and timestamp <= ? and warranty >= ? order by timestamp DESC','publish', $server_time, $server_time);
my $magazine_categories = [];# = $mag_cat->hashes;
my $articles = $articulation->hashes;
foreach my $mc ( @{$articles} ) {
unless ( grep { $_->{'app'} eq $mc->{'category'} } @{$magazine_categories}) {
push @{$magazine_categories}, { app => $mc->{'category'} };
}
}
if ($c->param('category')) {
$articulation = &subs::db_query('select * from magazine where status=? and category=? and timestamp <= ? and warranty >= ? order by timestamp DESC','publish',$c->param('category'), $server_time, $server_time);
}
else {
$articulation = &subs::db_query('select * from magazine where status=? and timestamp <= ? and warranty >= ? order by timestamp DESC','publish', $server_time, $server_time);
}
$articles = $articulation->hashes;
foreach my $mc ( @{$articles} ) {
$mc->{'public'} = &subs::setting_grabber({ app => &subs::unformat_name($mc->{'title'}), setting => 'public' });
}
my $ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/manager/ws';
my $mail_ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/mail/ws';
my $paperboy_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/observer/ws';
my ($website,$header) = &website_preloader($c);
my $my_name = $c->param('name') || &subs::setting_grabber({ app => 'me', setting => 'my_name' });
my %data = (
template => 'homepage',
title => $name,
articles => $articles,
mail_ws_url => $mail_ws_url,
paperboy_url => $paperboy_url,
website => $website,
header => $header,
my_name => $my_name,
magazine_categories => $magazine_categories,
config => &subs::config_reader(),
device => &subs::device_setter(),
string => &subs::random_string_creator(),
newsstand => &subs::statement_grabber(),
pseudonyms => &pseudonym_maker('manager',''),
ws_url => $ws_url,
advertise_watching => &subs::setting_grabber({ app => 'me', setting => 'advertise_watching' })
);
unless ($c->param('window_maker')) {
$data{'layout'} = 'homepage';
}
my $homepage = $c->render_to_string(
%data
);
return $homepage;
}
get '/manager/register_grabber' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $returner = ®ister_grabber($app);
$c->render(json => $returner);
};
sub register_grabber($app) {
my $timestamp = &subs::rightNow();
my $returner = { timestamp => $timestamp };
my $c = app->build_controller;
foreach my $att ( qw/model option option_category subcategory/ ) {
$returner->{'html'} .= $c->render_to_string(
template => 'pos/attributes',
att => $att,
a => $app
);
}
return $returner
}
get '/store' => sub ($c) {
&store_maker($c);
};
get '/manager/store' => sub($c) {
my $timestamp = $c->param('timestamp');
my $contents = &store_maker($c);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'store', contents => $contents }, $timestamp);
$c->render(text => $website);
};
sub store_maker($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $cat = &subs::db_query('select * from settings where setting=? and value=? and device=?','pos','category',$device);
my $categories = $cat->hashes;
my $timestamp = &subs::rightNow();
my $settings = &subs::settings_grabber({ app => 'store' });
foreach my $s ( @{$categories} ) {
my $app = $s->{'app'};
$s->{'settings'} = &subs::settings_grabber({ app => $app });
}
my $mail_ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/mail/ws';
my $paperboy_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/observer/ws';
my $ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/manager/ws';
my $advertise_watching = &subs::setting_grabber({ app => 'me', setting => 'advertise_watching' });
if ($c->param('window_maker') eq 'yes') {
return $c->render_to_string(
template => 'store/store',
string => $random_caching_string,
categories => $categories,
newsstand => &subs::statement_grabber(),
ws_url => $ws_url,
mail_ws_url => $mail_ws_url,
paperboy_url => $paperboy_url,
config => &subs::config_reader(),
advertise_watching => $advertise_watching,
my_name => $c->session('name'),
pseudonyms => &pseudonym_maker('manager',''),
window_maker => $c->param('window_maker'),
settings => $settings
);
}
else {
$c->render(
template => 'store/store',
layout => 'store',
string => $random_caching_string,
categories => $categories,
newsstand => &subs::statement_grabber(),
ws_url => $ws_url,
mail_ws_url => $mail_ws_url,
paperboy_url => $paperboy_url,
config => &subs::config_reader(),
advertise_watching => $advertise_watching,
my_name => $c->session('name'),
pseudonyms => &pseudonym_maker('manager',''),
window_maker => $c->param('window_maker')
);
}
}
get '/store/category_grabber' => sub ($c) {
my $category = &subs::unformat_name($c->param('category'));
my $subcategory = &subs::unformat_name($c->param('subcategory'));
my $types = eval { return decode_json $c->param('types') } || [];
my $count = $c->param('count') || '';
my ($db,$database,$sql) = &subs::database_grabber();
my $itemq = &subs::db_query('select * from settings where setting=? and value=? and device=?','category',$category,$device);
my $items = $itemq->hashes;
$items = &store_item_merchandiser($items,$types);
@{$items} = grep { $_->{'settings'}->{'public'} eq 'on' } @{$items} unless $c->session('privilege') eq 'citizen';
if ($subcategory) {
@{$items} = grep { $_->{'settings'}->{'subcategory' . $count} eq $subcategory } @{$items};
}
if (scalar @{$types} > 0) {
my @temp_items;
foreach my $type ( @{$types} ) {
push @temp_items, grep { $_->{'settings'}->{'pos'} eq $type } @{$items};
}
@{$items} = @temp_items;
}
my $subcategories;
if ($subcategory) {
$subcategories = &subs::db_query('select * from subcategory where app=?', $subcategory)->hashes;
$count++;
}
else {
$subcategories = &subs::db_query('select * from subcategory where app=?', $category)->hashes;
}
my $subcategories_text;
foreach my $sub ( @{$subcategories} ) {
$sub->{'settings'} = &subs::settings_grabber({ app => $sub->{'name'} });
$subcategories_text .= '
' . &subs::format_name($sub->{'name'}) .
'
';
}
my $rendered = $c->render_to_string(
template => 'store/category',
items => $items,
category => $category
);
my $returner = {
content => $rendered,
category => $category,
subcategories => $subcategories_text
};
$c->render(json => $returner);
};
post '/store/search' => sub($c) {
my $search = &subs::unformat_name($c->param('search'));
my $timestamp = $c->param('timestamp');
my $types = eval { return decode_json $c->param('types') } || [];
my $items = &subs::db_query('select distinct(app) as app,* from settings where setting=? and app like ? and device=?', 'pos', '%' . $search . '%',$device)->hashes;
my @temp_items;
foreach my $st ( @gb::store_types ) {
push @temp_items, grep { $_->{'value'} eq $st } @{$items};
}
@{$items} = sort { $a->{'app'} cmp $b->{'app'} } @temp_items;
$items = &store_item_merchandiser($items,$types);
my $rendered = $c->render_to_string(
template => 'store/category',
items => $items,
);
my $returner = {
content => $rendered
};
$c->render(json => $returner);
};
sub markup_adjuster($markup) {
if ($markup =~ /%$/gi) {
$markup =~ s/[^0-9.]//gi;
$markup = abs(($markup / 100)) + 1;
}
return $markup;
}
sub store_item_merchandiser($items,$types) {
my $universal_markup = &subs::setting_grabber({ app => 'me', setting => 'markup' }) || '5%';
my $markup = $universal_markup;
if ($markup =~ /%$/gi) {
$markup =~ s/[^0-9.]//gi;
$markup = abs(($markup / 100));
}
foreach my $i ( @{$items} ) {
$i->{'settings'} = &subs::settings_grabber({ app => $i->{'app'} });
$markup = $i->{'settings'}->{'markup'} || $universal_markup;
if ($markup =~ /%$/gi) {
$markup =~ s/[^0-9.]//gi;
$markup = abs(($markup / 100));
}
my $models = &subs::db_query('select * from model where app = ?', $i->{'app'})->hashes;
my $options = &subs::db_query('select * from option where app = ?', $i->{'app'})->hashes;
my $seen = 0;
foreach my $mo ( @{$models}, @{$options} ) {
if ($mo->{'def'} eq 'on') {
if ($mo->{'price'}) {
$i->{'price'} += $mo->{'price'} * ($mo->{'quantity'});
$seen += 1;
}
elsif ($mo->{'cost'}) {
$i->{'price'} += $mo->{'cost'} * ($mo->{'quantity'}) * $markup;
$seen += 1;
}
}
}
if ($seen == 0) {
@{$i->{'models'}} = sort { $a->{'price'} cmp $b->{'price'} } @{$models};
if (scalar @{$i->{'models'}} > 0) {
if ($i->{'models'}[0]->{'price'}) {
$i->{'price'} = $i->{'models'}[0]->{'price'};
}
elsif ($i->{'models'}[0]->{'cost'}) {
$i->{'price'} = $i->{'models'}[0]->{'cost'} * $markup;
}
}
}
}
if (scalar @{$types} > 0) {
my @temp_items;
foreach my $type ( @{$types} ) {
push @temp_items, grep { $_->{'settings'}->{'pos'} eq $type } @{$items};
}
@{$items} = @temp_items;
}
return $items;
}
get '/store/item' => sub ($c) {
my $item = {};
my $manufacturer = &subs::unformat_name($c->param('manufacturer'));
$item->{'app'} = &subs::unformat_name($c->param('item'));
$item->{'settings'} = &subs::settings_grabber({ app => $item->{'app'} });
my @manufacturers;
$item->{'models'} = &subs::db_query('select * from model where app = ? order by price', $item->{'app'})->hashes;
my $markup = &markup_adjuster($item->{'settings'}->{'markup'} || &subs::setting_grabber({ app => 'me', setting => 'markup' }) || '5%');
if (scalar @{$item->{'models'}} > 0) {
if ($item->{'models'}[0]->{'markup'}) {
$markup = &markup_adjuster($item->{'models'}[0]->{'markup'});
}
if ($item->{'models'}[0]->{'price'}) {
$item->{'price'} = $item->{'models'}[0]->{'price'};
}
elsif ($item->{'models'}[0]->{'cost'}) {
$item->{'price'} = $item->{'models'}[0]->{'cost'} * $markup;
$item->{'cost'} = $item->{'models'}[0]->{'cost'};
}
else {
$item->{'price'} = $item->{'settings'}->{'worth'} * $markup;
}
$item->{'models'}[0]->{'select'} = 'on';
}
else {
$item->{'price'} = $item->{'settings'}->{'worth'} * $markup;
}
$item->{'options'} = &subs::db_query('select * from option where app = ?', $item->{'app'})->hashes;
my $option_categories = {};
foreach my $att ( @{$item->{'models'}}, @{$item->{'options'}} ) {
if ($att->{'manufacturer'}) {
push @manufacturers, $att->{'manufacturer'} unless grep { $_ eq $att->{'manufacturer'} } @manufacturers;
}
if ($att->{'markup'}) {
$markup = &markup_adjuster($att->{'markup'});
}
if ($att->{'file'}) {
$att->{'file'} = eval { return decode_json $att->{'file'} } || [];
}
if ($att->{'price'}) {
}
else {
$att->{'price'} = $att->{'cost'} * $markup;
}
if ($att->{'discount'}) {
if ($att->{'discount'} =~ /%$/gi) {
$att->{'discount'} =~ s/[^0-9.]//gi;
$att->{'discount'} = abs($att->{'price'} * ($att->{'discount'} / 100));
}
$att->{'discount'} = abs($att->{'discount'}) * -1;
}
$att->{'characteristics'} = eval { return decode_json $att->{'characteristics' } } || [];
if (my @oc = grep { $_->{'name'} eq 'option_category' } @{$att->{'characteristics'}} ) {
foreach my $o ( @oc ) {
my $option_category = &subs::db_select('option_category', undef, { uuid => $o->{'value'} })->hashes;
if ($option_category->[0]->{'file'}) {
$option_category->[0]->{'file'} = eval { return decode_json $option_category->[0]->{'file'} } || [];
}
$option_category->[0]->{'characteristics'} = eval { return decode_json $option_category->[0]->{'characteristics'} } || [];
$item->{'option_categories'}->{$option_category->[0]->{'name'}} = $option_category->[0];
foreach my $occ ( @{$option_category->[0]->{'characteristics'}} ) {
$item->{'option_categories'}->{$option_category->[0]->{'name'}}->{$occ->{'name'}} = $occ->{'value'};
}
push @{$option_categories->{$option_category->[0]->{'name'}}}, $att;
}
@{$att->{'characteristics'}} = grep { $_->{'name'} ne 'option_category' } @{$att->{'characteristics'}};
}
}
if ($manufacturer) {
@{$item->{'options'}} = grep { $_->{'manufacturer'} eq $manufacturer } @{$item->{'options'}};
@{$item->{'models'}} = grep { $_->{'manufacturer'} eq $manufacturer } @{$item->{'models'}};
}
if ($item->{'settings'}->{'public'} eq 'on' || $c->session('privilege') eq 'citizen') {
my $fapptsq = &subs::db_query('select file from appointments where app = ? and file is not null', $item->{'app'})->hashes;
$item->{'files'} = [];
foreach my $t ( qw/ specs description / ) {
$item->{'settings'}->{$t} =~ s/\n/
/gi;
}
foreach my $f ( @{$fapptsq} ) {
$f->{'files'} = eval { return decode_json $f->{'file'} } || [];
foreach my $fi ( grep { $_->{'function'} ne 'receipt' } @{$f->{'files'}} ) {
push @{$item->{'files'}}, $fi if -e $fi->{'f'} && $fi->{'visible'} ne 'unchecked';
}
}
if (!$item->{'settings'}->{'main_image'} && scalar @{$item->{'files'}} > 0) {
$item->{'settings'}->{'main_image'} = $item->{'files'}->[0]->{'f'};
}
$item->{'template'} = $c->render_to_string(
template => 'store/item',
item => $item,
markup => $markup,
option_categories => $option_categories,
manufacturers => \@manufacturers,
settings => &subs::settings_grabber({ app => 'store' })
);
}
else {
$item = { template => $c->render_to_string(template => 'guest_layouts/denial') };
}
$c->render(json => $item);
};
get '/manager/store/customer_search' => sub($c) {
my $search = $c->param('search');
my $movement = $c->param('movement');
if ($search) {
my @search = split ' ', $search;
my $s = join '%', @search;
$search = '%' . $s . '%';
my ($db) = &subs::database_grabber();
my $results;
if ($movement eq 'expense') {
$results = &subs::db_query('select DISTINCT(app) from settings where app like ? and setting=? and (value=? or value =? or value=? or value=? or value=?) LIMIT 20', $search,'pos','vendor','person','government','institution','corporation')->hashes;
}
elsif ($movement eq 'income') {
$results = &subs::db_query('select DISTINCT(app) from settings where app like ? and setting=? and (value=? or value =? or value=? or value=? or value=?) LIMIT 20', $search,'pos','customer','person','government','institution','corporation')->hashes;
}
foreach my $r ( @{$results} ) {
$r->{'uuid'} = &subs::setting_grabber({ app => $r->{'app'}, setting => 'uuid' });
}
my $resulted = $c->render_to_string(template => 'search/customer', results => $results);
$c->render(json => { results => $resulted, count => scalar @{$results} });
}
else {
$c->render(json => { count => 0 });
}
};
get '/manager/store/customer_load' => sub($c) {
my ($db) = &subs::database_grabber();
my $cx = $c->param('cx');
my $customer = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx })->hashes->[0];
my $settings = &subs::settings_grabber({ app => $customer->{'app'} });
my $content = $c->render_to_string(
template => 'store/customer',
cx => $cx,
customer => $customer,
settings => $settings,
);
$c->render(json => { content => $content, cx => $cx, formatted_name => &subs::format_name($customer->{'app'}), settings => $settings });
};
post '/store/quote/save' => sub($c) {
my $timestamp = $c->param('timestamp');
my $item = $c->param('item');
my $quote_uuid = $c->param('uuid');
my $cx = $c->param('cx');
my $movement = $c->param('movement');
if ($cx) {
my $quote = eval { return decode_json $c->param('quote') } || { info => {}, options => [], model => {}, numbers => {}};
my $customer_s = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx })->hashes->[0];
my $s = &subs::settings_grabber({ app => $customer_s->{'app'} });
$quote->{'id'} = "e_id_maker($quote);# unless $quote->{'id'};
my $jquote = encode_json $quote;
&appointment_writer($c, { data => $jquote, movement => $movement, app => $customer_s->{'app'}, duration => &subs::time_abbrev_translator('10s'), timestamp => $timestamp, type => 'quote' });
$c->render(json => { quote => $quote });
}
else {
$c->render(json => { error => 'no customer' });
}
};
sub quote_id_maker($quote) {
my $server_time = &subs::rightNow();
my $time = localtime($server_time / 1000);
my $id = ($time->[4] + 1) . ($time->[3]) . ($time->[5] + 1900);
my $today_quotes = &subs::db_query('select type,data,uuid from appointments where ( type=? or type=? or type=? or type=? ) and timestamp > ? and timestamp < ? order by server_time',
'order','invoice','quote','purchase', &subs::ago_calc('1d',$server_time), &subs::ago_calc('-1d',$server_time))->hashes;
my $quote_number = 1;
foreach my $q ( @{$today_quotes} ) {
my $qd = eval { return decode_json $q->{'data'} } || {};
my @qid = split '-', $qd->{'id'};
$quote_number = $qid[1] + 1 unless $quote_number > $qid[1] + 1;
}
$id .= '-' . $quote_number . &subs::shorthand_name(&subs::signatorial_designer(),3);
return $id;
}
post '/store/quote/delete' => sub($c) {
my $uuid = $c->param('uuid');
my $cx_uuid = $c->param('cx_uuid');
my $timestamp = $c->param('timestamp');
my $type = $c->param('type');
my $server_time = $c->param('server_time');
my $customer_s = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx_uuid })->hashes->[0];
my $data = { type => $type, app => $customer_s->{'app'}, uuid => $uuid };
&delete_app($customer_s->{'app'},$uuid,$server_time,'quote_delete');
$c->render(text => $data);
};
post '/store/quote/move' => sub($c) {
my $timestamp = $c->param('timestamp');
my $cx_uuid = $c->param('cx_uuid');
my $uuid = $c->param('uuid');
my $action = $c->param('action');
my $type = $c->param('type');
my $customer_s = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx_uuid })->hashes->[0];
my $data = { type => $type, app => $customer_s->{'app'}, uuid => $uuid };
my $appt = &subs::db_select('appointments', undef, $data)->hashes->[0];
if ($action eq 'invoice' && $appt->{'type'} eq 'quote') {
my $d = eval { return decode_json $appt->{'data'} };
$d->{'numbers'}->{'balance'} = $d->{'numbers'}->{'total'};
$appt->{'data'} = encode_json $d;
}
$appt->{'type'} = $action;
$appt->{'status'} = 'open';
$appt->{'server_time'} = &subs::rightNow();
$appt->{'uuid'} = &subs::random_string_creator(25);
&subs::db_insert('appointments', $appt, $data);
$c->render(text => 'ok');
};
get '/store/quote/load' => sub($c) {
my $uuid = $c->param('uuid');
my ($db) = &subs::database_grabber();
my $quote = &subs::db_select('appointments', undef, { uuid => $uuid })->hashes->[0];
if ($quote->{'data'}) {
my $data = decode_json $quote->{'data'};
$c->render(json => $data);
}
else {
$c->render(json => {});
}
};
get '/store/print' => sub($c) {
my $type = $c->param('type');
my $cx_uuid = $c->param('cx_uuid');
my $uuid = $c->param('uuid');
my $printer = &store_printer({
type => $type,
cx_uuid => $cx_uuid,
uuid => $uuid
});
my $header = $c->render_to_string(
%{$printer}
);
$c->render(text => $header);
};
get '/public_view/:type/:uuid/:cx_uuid' => sub ($c) {
my $uuid = $c->stash('uuid');
my $type = $c->stash('type');
my $cx_uuid = $c->stash('cx_uuid');
my $printer = &store_printer({
uuid => $uuid,
type => $type,
cx_uuid => $cx_uuid
});
$printer->{'layout'} = 'public_view';
$c->render(
%{$printer}
);
};
sub store_printer($data) {
my $type = $data->{'type'};
my $cx_uuid = $data->{'cx_uuid'};
my $uuid = $data->{'uuid'};
my $c = app->build_controller;
my $customer_s = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx_uuid })->hashes->[0];
my $cx_settings = &subs::settings_grabber({ app => $customer_s->{'app'} });
my $print_date = 0;
my $due = &subs::setting_grabber({ app => 'me', setting => 'payment_due_date' });
my $due_date;
my $cx = $cx_settings;
$cx->{'app'} = $customer_s->{'app'};
my $registers;
if ( $uuid eq 'all' ) {
$registers = &subs::db_select('appointments', undef, { type => $type, app => $cx->{'app'} })->hashes;
}
else {
$registers = &subs::db_select('appointments', undef, { type => $type, app => $cx->{'app'}, uuid => $uuid })->hashes;
}
my (@i);
my $totals = { price => 0, tax => 0, discount => 0, total => 0 };
my $payments = [];
foreach my $reg ( @{$registers} ) {
$reg->{'data'} = eval { return decode_json $reg->{'data'} } || {};
push @i, $reg->{'data'}->{'id'};
foreach my $t ( qw/subtotal discount tax aux total balance/ ) {
$totals->{$t} += $reg->{'data'}->{'numbers'}->{$t};
}
if ($reg->{'timestamp'} > $print_date) {
$print_date = $reg->{'timestamp'};
if ($due) {
$due_date = &subs::ago_calc($due, $print_date);
}
else {
$due_date = $print_date;
}
}
if ($reg->{'data'}->{'payments'}) {
push @{$payments}, @{$reg->{'data'}->{'payments'}};
}
}
my $id = join '
', @i;
my $address = $c->tx->local_address;
if ($config->{'domain'}) {
my @d = split '\.', $config->{'domain'};
if (scalar @d > 2) {
shift @d;
$address = join '.', @d;
my $ping = `timeout .5 ping -c 1 $address`;
unless ($ping =~ /ttl/gi) {
$address = $config->{'domain'};
}
}
else {
$address = $config->{'domain'};
}
}
my $qr = 'https://' . $address . ':3000/public_view/' . $type . '/' . $uuid . '/' . $cx_uuid ;
my $qr_img = `qrencode -o - $qr`;
$qr_img = 'data:image/png;base64,' . encode_base64($qr_img);
my $returner = {
template => '/store/printer/header',
registers => $registers,
type => $type,
uuid => $uuid,
cx => $cx_settings,
qr_code => $qr,
qr_img => $qr_img,
id => $id,
totals => $totals,
payments => $payments,
print_date => localtime( $print_date / 1000 )->strftime('%b %d %Y'),
due_date => localtime( &subs::ago_calc($due, $print_date) / 1000 )->strftime('%b %d %Y')
};
return $returner;
}
get '/manager/store/customer_list' => sub($c) {
my $cx = $c->param('cx');
my $list_type = $c->param('list');
my $type = $list_type;
$type =~ s/s$//;
my ($db) = &subs::database_grabber();
my $customer = &subs::db_select('settings', undef, { setting => 'uuid', value => $cx })->hashes->[0];
if ($customer->{'app'}) {
my $totals = {};
my $settings = &subs::settings_grabber({ app => $customer->{'app'}});
my $list = &subs::db_select('appointments', undef, { type => $type, app => $customer->{'app'} })->hashes;
foreach my $l ( @{$list} ) {
$l->{$type} = eval { return decode_json $l->{'data'} } || {};
foreach my $number ( keys %{$l->{$type}->{'numbers'}} ) {
$totals->{$number} += $l->{$type}->{'numbers'}->{$number};
}
}
my $content = $c->render_to_string(
template => 'store/list',
list => $list,
type => $type,
settings => $settings,
customer => $customer,
totals => $totals
);
$c->render(json => { content => $content, cx => $cx, list => $list, settings => $settings });
}
else {
$c->render(json => { content => 'no' });
}
};
post '/manager/configure/attribute_copy' => sub($c) {
my $uuid = $c->param('uuid');
my $att = $c->param('att');
my $app = &subs::unformat_name($c->param('app'));
my $pre_app = &subs::unformat_name($c->param('pre_app'));
my $returner = { app => $app, att => $att, uuid => $uuid, pre_app => $pre_app };
my $attribute = &subs::db_select($att, undef, { uuid => $uuid, app => $pre_app })->hashes->[0];
$attribute->{'characteristics'} = eval { return decode_json $attribute->{'characteristics'} } || [];
if ($att eq 'option') {
my @category = grep { $_->{'name'} eq 'option_category' } @{$attribute->{'characteristics'}};
my $cat = $category[0];
my $oc = &subs::db_select('option_category', undef, { app => $pre_app, uuid => $cat->{'value'} })->hashes->[0];
my $oc_check = &subs::db_select('option_category', undef, { app => $app, name => $oc->{'name'} })->hashes;
unless ( scalar @{$oc_check} > 0 ) {
$oc->{'app'} = $app;
$oc->{'server_time'} = &subs::rightNow();
$oc->{'uuid'} = &subs::random_string_creator(100);
&subs::db_insert('option_category', $oc);
}
else {
$oc = $oc_check->[0];
}
$cat->{'value'} = $oc->{'uuid'};
$returner->{'option_category'} = $oc;
}
$attribute->{'characteristics'} = encode_json $attribute->{'characteristics'};
$attribute->{'server_time'} = &subs::rightNow();
$attribute->{'uuid'} = &subs::random_string_creator(101);
$attribute->{'app'} = $app;
my $att_check = &subs::db_select($att, undef, { name => $attribute->{'name'}, app => $app })->hashes;
if (scalar @{$att_check} > 0 ) {
my $ac = $att_check->[0];
$attribute->{'uuid'} = $ac->{'uuid'};
&subs::db_update($att, $attribute, { uuid => $ac->{'uuid'}, app => $ac->{'app'}, name => $ac->{'name'} });
}
else {
&subs::db_insert($att, $attribute);
}
$returner->{'template'} = $c->render_to_string(template => 'pos/attributes', att => $att, a => $app);
$returner->{'attribute'} = $attribute;
$c->render(json => $returner);
};
post '/manager/store/:att/save' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $name = &subs::unformat_name($c->param('name'));
my $att = $c->stash('att');
my $cost = $c->param('cost');
my $price = $c->param('price');
my $uuid = $c->param('uuid');
my $timestamp = $c->param('timestamp');
my $discount = $c->param('discount');
my $unit = $c->param('unit') || $name;
my $markup = $c->param('markup');
my $category = $c->param('category');
my $description = $c->param('description');
my $manufacturer = $c->param('manufacturer');
my $def = $c->param('def');
my $save_app = $c->param('save_app');
my $quantity = $c->param('quantity');
my $delay_start = $c->param('delay_start');
my $delay_stop = $c->param('delay_stop');
if ($quantity =~ /[a-zA-Z]/) {
my $gunit = $quantity;
$gunit =~ s/[^a-zA-Z]//gi;
$unit = $gunit if grep { $_ eq $gunit } keys %{$gb::measures};
$quantity =~ s/[^0-9.]//gi;
}
if ($uuid ne 'new') {
if ($def eq 'on' && $att eq 'model') {
&subs::db_update($att, { def => 'off' }, { app => $app })->hashes;
}
}
my $server_time = &subs::rightNow();
my $returner = {
app => $app,
name => $name,
cost => $cost,
price => $price,
discount => $discount,
markup => $markup,
description => $description,
uuid => &subs::random_string_creator(50),
timestamp => $timestamp,
server_time => $server_time,
manufacturer => $manufacturer,
def => $def,
save_app => $save_app,
quantity => $quantity,
unit => $unit,
delay_start => $delay_start,
delay_stop => $delay_stop
};
$returner->{'category'} = $category if $att eq 'option_category' || $att eq 'subcategory';
if ($uuid eq 'new') {
&subs::db_insert($att, $returner);
}
else {
$returner->{'uuid'} = $uuid;
&subs::db_update($att, $returner, { uuid => $uuid });
}
my $attd = $att;
$attd = s/_//gi;
$returner->{'template'} = $c->render_to_string(template => 'pos/attributes', att => $att, a => $app);
$c->render(json => $returner);
};
post '/manager/configure/attribute_upload' => sub($c) {
my $timestamp = $c->param('timestamp');
my $attribute = $c->param('attribute');
my $uuid = $c->param('uuid');
my $app = $c->param('app');
my @uploads = @{$c->req->uploads};
my $image;
my $returner;
my $att_files = &subs::db_select($attribute, undef, { uuid => $uuid, app => $app })->hashes->[0];
my $atf = eval { return decode_json $att_files->{'file'} } || [];
my (@uploaded_files,$linux_file,$upload_type);
foreach my $u ( @uploads ) {
my $server_time = &subs::rightNow();
$timestamp++;
my $filen = &subs::unformat_name($u->filename);
my @f = split /\./, $filen;
my $ext = pop @f;
$filen = join '.', @f;
my $fn = $filen . '_' . $timestamp . '.' . $ext;
my $upload = {
type => $u->headers->content_type,
path => $u->asset->path,
filename => $fn,
size => $u->size,
};
$app = &subs::unformat_name($app);
my $init = &subs::setting_initializer($app,$timestamp);
$app = $init->{'app'};
push @uploaded_files, $upload;
my ($folder,$location);
if ($upload->{'type'} =~ /audio/gi) {
$upload_type = 'audio';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'rec_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /video/gi) {
$upload_type = 'video';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'video_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /pdf/gi) {
$upload_type = 'scan';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'document_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /application/gi) {
$upload_type = 'software';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'download_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /image/gi) {
$upload_type = 'image';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'photo_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
else {
$folder = &subs::setting_grabber( { app => 'misc', setting => 'download_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
`mkdir -p $location` unless -e $location;
my $filename = $location . '/' . $upload->{'filename'};
$u->move_to($filename);
$linux_file .= `file $filename`;
if ($upload->{'filename'} =~ /avi$|mkv$/gi) {
my $old_filename = $filename;
$filename =~ s/avi$|mkv$/mp4/;
my $tn_o = &subs::terminal_name($old_filename);
my $tn_f = &subs::terminal_name($filename);
threads->create(sub() {
`ffmpeg -i $tn_o $tn_f & exit /b`;
`shred -u $tn_o`;
&subs::file_encrypter({ app => $app });
});
}
my $filing = { f => $filename, att => $attribute, att_uuid => $uuid, uuid => &subs::random_string_creator(18), type => $upload_type, server_time => &subs::rightNow() };
push @{$returner}, $filing;
push @{$atf}, $filing;
}
my $jfile = encode_json $returner;
my $jafile = encode_json $atf;
&subs::db_update($attribute, { file => $jafile, server_time => &subs::rightNow() }, { uuid => $uuid, app => $app });
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
notes => &subs::note_encrypter($c->session('suds'),$linux_file),
type => $upload_type,
file => $jfile,
uuid => &subs::random_string_creator(20),
duration => '1000'
};
&appointment_writer($c,$write);
&subs::file_encrypter({ app => $app });
$c->render(json => $returner);
};
post '/manager/store/attribute_characteristic_setter' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $att = &subs::unformat_name($c->param('att'));
my $app = $c->param('app');
my $att_uuid = $c->param('att_uuid');
my $uuid = $c->param('uuid');
my $input = $c->param('input');
my $value = $c->param('value');
my $unit;
if ($value =~ /[a-zA-Z0-9]/) {
my $gunit = $value;
$gunit =~ s/[^a-zA-Z]//gi;
if (grep { $_ eq $gunit } keys %{$gb::measures}) {
$unit = $gunit;
$value =~ s/[^0-9.]//gi;
}
}
my $type = $c->param('type');
my ($db,$database) = &subs::database_grabber();
my $attributes = &subs::db_select($att, ['uuid','characteristics',], { uuid => $att_uuid })->hashes;
my $attr = $attributes->[0];
my $chars = eval { return decode_json $attr->{'characteristics'} } || [];
my $data = {
uuid => &subs::random_string_creator(25),
$input => $value,
timestamp => $timestamp
};
if ($type eq 'select') {
$data = {
name => $input,
value => $value,
timestamp => $timestamp,
uuid => $uuid
};
if ($uuid eq 'new') {
my $measurement = $value;
$measurement =~ s/[0-9.,-]//gi;
$data->{'uuid'} = &subs::random_string_creator(25);
}
else {
@{$chars} = grep { $_->{'uuid'} ne $uuid } @{$chars};
}
}
elsif ($uuid eq 'new') {
}
else {
my @cdata = grep { $_->{'uuid'} eq $uuid } @{$chars};
@{$chars} = grep { $_->{'uuid'} ne $uuid } @{$chars};
$cdata[0]->{$input} = $value;
$cdata[0]->{'timestamp'} = $timestamp;
$data = $cdata[0];
$data->{'unit'} = $unit if $unit;
}
unshift @{$chars}, $data;
my $json_chars = encode_json $chars;
&subs::db_update($att, { characteristics => $json_chars }, { uuid => $att_uuid });
$c->render(json => { template => $c->render_to_string(template => 'pos/attributes', att => $att, a => $app), attribute => $data });
};
post '/manager/store/characteristic_delete' => sub($c) {
my $uuid = $c->param('uuid');
my $att_uuid = $c->param('att_uuid');
my $att = $c->param('att');
my ($db) = &subs::database_grabber();
my $attribute = &subs::db_select($att, undef, { uuid => $att_uuid })->hashes->[0];
my $chars = eval { return decode_json $attribute->{'characteristics'} } || [];
@{$chars} = grep { $_->{'uuid'} ne $uuid } @{$chars};
my $json_chars = encode_json $chars;
&subs::db_update($att, { characteristics => $json_chars }, { uuid => $att_uuid });
$c->render(json => { uuid => $uuid });
};
post '/manager/store/attribute_delete' => sub($c) {
my $uuid = $c->param('uuid');
my $att = $c->param('att');
my ($db,$database) = &subs::database_grabber();
&subs::db_delete($att, { uuid => $uuid });
$c->render('text' => 'ok');
};
post '/manager/store/appointment_model_migration' => sub($c) {
my $att = $c->param('att');
my $matt = $c->param('matt');
my $app = $c->param('app');
my $uuid = $c->param('uuid');
my $original = &subs::db_select($att, undef, { app => $app, uuid => $uuid })->hashes->[0];
&subs::db_delete($att, { app => $app, uuid => $uuid });
&deletion_registration({ table => $att, uuid => $uuid, server_time => $original->{'server_time'} });
$original->{'server_time'} = &subs::rightNow();
&subs::db_insert($matt, $original);
my $returner = ®ister_grabber($app);
$c->render(json => $returner);
};
post '/manager/store/appointment_model_selector' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $appt_uuid = $c->param('appt_uuid');
my $server_time = &subs::rightNow();
my $quantity = $c->param('quantity');
my $manufacturer = $c->param('manufacturer');
my $unit = $c->param('unit');
my $source = $c->param('source');
if ($quantity =~ /[a-zA-Z]/) {
my $gunit = $quantity;
$gunit =~ s/[^a-zA-Z]//gi;
$unit = $gunit if grep { $_ eq $gunit } keys %{$gb::measures};
$quantity =~ s/[^0-9.]//gi;
}
my $app = $c->param('app');
my $appt = &subs::db_query('select * from appointments where uuid=? and app =?', $appt_uuid, $app)->hashes->[0];
my $cause = $c->param('cause');
my $existing_model = eval { return decode_json $appt->{'model'} } || {};
my $m = &subs::db_select('model', undef, { uuid => $uuid })->hashes->[0];
if ($cause eq 'model') {
$quantity = $m->{'quantity'};
$unit = $m->{'unit'};
}
my $model = encode_json { uuid => $m->{'uuid'}, timestamp => $timestamp, quantity => ( $quantity), name => $m->{'name'}, unit => ( $unit) };
if ($source ne 'transaction') {
if ($existing_model->{'uuid'}) {
my $del = &subs::db_select('appointments', undef, { source_uuid => $appt->{'uuid'}, app => $existing_model->{'name'} })->hashes;
foreach my $d ( @{$del} ) {
&delete_app($d->{'app'},$d->{'uuid'},$d->{'server_time'},'appointment_model_selector');
}
}
if ( $m->{'save_app'} eq 'on') {
&subs::source_appt_writer($m, {
app => $appt->{'app'},
uuid => $appt->{'uuid'},
type => $appt->{'type'},
duration => $appt->{'duration'},
timestamp => $appt->{'timestamp'},
unit => $unit,
quantity => $quantity,
project => $appt->{'project'},
manufacturer => $manufacturer
}, 'model');
}
$manufacturer = $m->{'manufacturer'} unless $manufacturer;
&subs::db_query('update appointments set server_time = ?, model=?, manufacturer=?, quantity=?, unit=? where uuid=?',$server_time,$model,$manufacturer,$quantity,$unit,$appt_uuid);
&Websocket::send($app, { console => 'appointmentDetailGrabber(\'' . $appt->{'app'} . '\',\'' . $appt->{'uuid'} .'\');' });
}
$c->render(json => $model);
};
post '/manager/store/appointment_option_selector' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $appt_uuid = $c->param('appt_uuid');
my $server_time = &subs::rightNow();
my $app = $c->param('app');
my $option = &subs::db_select('option', undef, { uuid => $uuid, app => $app })->hashes->[0];
my $manufacturer = $c->param('manufacturer');
my $quantity = $c->param('quantity');
my $unit = $c->param('unit');
if ($quantity =~ /[a-zA-Z]/) {
my $gunit = $quantity;
$gunit =~ s/[^a-zA-Z]//gi;
$unit = $gunit if grep { $_ eq $gunit } keys %{$gb::measures};
$quantity =~ s/[^0-9.]//gi;
}
my $select = $c->param('select');
my $all_options = eval { return decode_json $c->param('all_options') } || [];
@{$all_options} = grep { $_->{'uuid'} ne $uuid } @{$all_options};
my $appt = &subs::db_query('select * from appointments where uuid=? and app = ?', $appt_uuid, $app)->hashes->[0];
my $options = eval { return decode_json $appt->{'options'} } || [];
if (scalar @{$options} == 0 ) {
foreach my $o ( @{$all_options} ) {
push @{$options}, { uuid => $o->{'uuid'}, quantity => $o->{'quantity'}, timestamp => &subs::rightNow(), unit => $o->{'unit'}, name => $o->{'name'} };
}
}
my @deletions = grep { $_->{'uuid'} eq $uuid } @{$options};
foreach my $deleters ( @deletions ) {
my $op = &subs::db_select('option', undef, { uuid => $deleters->{'uuid'}, app => $app })->hashes->[0];
my $del = &subs::db_select('appointments', undef, { source_uuid => $appt->{'uuid'}, app => $op->{'name'} })->hashes->[0];
&delete_app($del->{'app'},$del->{'uuid'},$del->{'server_time'},'appointment_option_Selector');
}
@{$options} = grep { $_->{'uuid'} ne $uuid } @{$options};
if ($select eq 'on') {
if ($quantity == 1 && $unit eq $app) {
$quantity = $option->{'quantity'};
$unit = $option->{'unit'};
my $settings = &subs::settings_grabber({ app => $option->{'name'} });
if (!$unit) {
$unit = $settings->{'unit'};
}
if (!$quantity) {
$quantity = $settings->{'quantity'};
}
if (!$unit) {
$unit = $app;
}
}
my $o = { uuid => $uuid, quantity => $quantity, timestamp => $timestamp, unit => $unit, name => $option->{'name'} };
push @{$options}, $o;
if ( $option->{'save_app'} eq 'on') {
&subs::source_appt_writer($o, {
app => $appt->{'app'},
uuid => $appt->{'uuid'},
type => $appt->{'type'},
quantity => $quantity,
unit => $unit,
duration => $appt->{'duration'},
timestamp => $appt->{'timestamp'},
manufacturer => $manufacturer,
project => $appt->{'project'}
}, 'option');
}
}
#if ( scalar @{$options} > 0 ) {
my $joptions = encode_json $options;
&subs::db_update('appointments', { options => $joptions, server_time => $server_time }, { app => $app, uuid => $appt_uuid });
#}
&Websocket::send($app, { console => 'appointmentDetailGrabber(\'' . $appt->{'app'} . '\',\'' . $appt->{'uuid'} .'\');' });
$c->render(json => $options);
};
get '/manager/configure/store_list' => sub($c) {
my $timestamp = $c->param('timestamp');
my $store = &store_setting_list();
$c->render(
template => 'configure/store_setting_list',
store => $store,
pos_list => $gb::pos
);
};
get '/manager/editor' => sub ($c) {
my $editor = &editor_maker($c);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'editor', contents => $editor }, $c->param('timestamp'));
$c->render(text => $website);
};
get '/manager/magazine/neighbour_publish' => sub($c) {
my $ip = $c->param('ip');
my $browser_tab_id = $c->param('browser_tab_id');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $remote_machine = &subs::db_select('remote_machines', undef, { uuid => $uuid, ip => $ip })->hashes->[0];
$remote_machine = &remote_useragent_maker({ ip => $ip, signatorial => $remote_machine->{'signatorial'}, rm => $remote_machine });
if ($remote_machine->{'ua'}) {
my ($db,$database,$sql) = &subs::database_grabber();
my $q = &subs::db_query('select * from magazine where status = ?', 'publish');
my $articles = $q->hashes;
my $json = encode_json $articles;
my $npq = &subs::db_query('select title,uuid from magazine where status != ?', 'publish');
my $nparticles = $npq->hashes;
my $npjson = encode_json $nparticles;
my $port_quest = &subs::db_query('select * from remote_machines where ip=?', $ip);
my $ports = $port_quest->hashes;
my $remote = $ports->[-1];
my $port = $remote->{'port'};
my $string = '/manager/magazine/publishing_receive';
my $remote_params = { articles => $json, nonpublished => $npjson };
my $res = eval { return $remote_machine->{'ua'}->insecure(1)->post('https://' . $ip . ':' . $port . $string => form => $remote_params)->result };
if ($res) {
$c->render('text' => $res->body);
}
else { $c->render('text' => 'no good'); }
}
else {
$c->render('text' => 'no idea');
}
};
post '/manager/magazine/publishing_receive' => sub($c) {
my $articles = eval { return decode_json $c->param('articles') } || {};
my $nonpublished = eval { return decode_json $c->param('nonpublished') };
my $timestamp = &subs::rightNow();
my ($db,$database,$sql) = &subs::database_grabber();
foreach my $a ( @{$articles} ) {
my $q = &subs::db_query('select * from magazine where uuid=?', $a->{'uuid'});
my $prev = $q->hashes;
my $category = &subs::setting_grabber({ app => $a->{'category'}, setting => 'pos' });
unless ($category eq 'category') {
my $pillow = &subs::unformat_name($a->{'category'} . ' category');
my $init = &subs::setting_initializer($pillow,$timestamp);
$a->{'category'} = $init->{'app'};
my $ass = &appointment_writer($c,{
app => $a->{'category'},
type => 'text',
timestamp => $timestamp,
});
}
if ($prev->[0]->{'uuid'}) {
&subs::db_update('magazine', $a, { uuid => $a->{'uuid'} });
}
else {
my $insert = &subs::db_insert('magazine', $a);
}
}
foreach my $a (@{$nonpublished}) {
&subs::db_query('update magazine set status=? where uuid=?', $a->{'status'}, $a->{'uuid'});
}
$c->render('text' => 'success');
};
sub editor_maker($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $uuid = $c->param('article_uuid') || '';
my $scope = $c->param('scope');
my $timestamp = $c->param('timestamp');
my $t = &{$subs::time_subs->{$scope}}($timestamp); #timestamp at beginning
my $t1 = ($timestamp - $t);
my $t2 = ($t1 + $timestamp + $t1);
my $articulation = &subs::db_query('select * from magazine order by timestamp DESC');# where timestamp >= ? and timestamp <= ?', $t, $t2);
my $mag_cat = &subs::db_query('select distinct(app) from settings where setting=? and value=?','pos','category');
my $magazine_categories = $mag_cat->hashes;
my $articles = $articulation->hashes;
my $contents = $c->render_to_string(
template => 'editor',
articles => $articles,
uuid => $uuid,
magazine_categories => $magazine_categories,
window_maker => $c->param('window_maker')
);
return $contents;
}
post '/manager/editor/save' => sub ($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $scope = $c->param('scope');
my $server_time = &subs::rightNow();
my $title = $c->param('title');
my $content = $c->param('content');
my $teaser = &subs::teaser_name($c->param('teaser')) . '...' || "";
my $uuid = $c->param('article_uuid');
my $text_colour = $c->param('text_colour');
my $background_colour = $c->param('background_colour');
my $status = $c->param('status');
my $category = $c->param('category');
my $image = $c->param('image');
my $warranty = &subs::ago_calc($c->param('warranty') || &subs::setting_grabber({ app => 'me', setting => 'warranty' }), $server_time);
my $previous_edition;
if ($uuid ne 'none') {
my $previous_editionq = &subs::db_query('select * from magazine where uuid=?', $uuid);
$previous_edition = $previous_editionq->hashes->[0];
}
my $timestamp = &subs::ago_calc($c->param('timestamp'), $server_time) || $server_time;
my $article = {
uuid => $uuid,
title => $title,
content => $content,
timestamp => $timestamp,
manager_file => &manager_file_maker($c->session('name')),
status => $status,
text_colour => $text_colour,
background_colour => $background_colour,
server_time => $server_time,
category => $category,
warranty => $warranty,
image => $image,
teaser => $teaser
};
if (!$previous_edition->{'uuid'} || $uuid eq 'none') {
$article->{'uuid'} = &subs::random_string_creator(100);
$uuid = $article->{'uuid'};
&subs::db_insert('magazine', $article);
}
else {
&subs::db_update('magazine', $article, { uuid => $uuid });
}
if (($status ne 'publish') || ( $timestamp >= $server_time || $warranty <= $server_time )) {
&paperRoute({ uuid => $article->{'uuid'}, remove => 'yes' });
}
elsif ($status eq 'publish') {
$article->{'art'} = $c->render_to_string(template => 'article', art => $article);
&paperRoute($article);
}
$c->render(json => { uuid => $uuid });
};
post '/manager/editor/delete' => sub ($c) {
my $uuid = $c->param('article_uuid');
my ($db,$database,$sql) = &subs::database_grabber();
&subs::db_query('delete from magazine where uuid = ?', $uuid);
$c->render('text' => 'ok');
};
hook before_dispatch => sub {
my ($c) = @_;
$c->session(expiration => 604800);
};
hook before_render => sub {
$database = '';
};
sub password_maker($c) {
my $sacred = $c->param('numerics');
my @uploads = @{$c->req->uploads};
my @numerics = split '', $sacred;
my ($secret,$ass);
my $count = scalar @numerics;
if (scalar @uploads > 0) {
foreach my $u ( @uploads ) {
my $size = $u->size;
if ($size > 10000000) {
&subs::say_it('way too big of a file!');
$c->rendered;
return 'noway';
}
$ass = $u->asset->slurp;
$ass = encode_base64($ass, "");
$ass =~ s/\\\n//gi;
my @asset = split '', $ass;
my $mid = scalar @asset / 2;
my $low_mid = (scalar @asset * .3333);
my $up_mid = (scalar @asset * .6666);
my $keys = [];
for (my $i = 1; $i <= $count; $i++) {
my $d = ($i / scalar @numerics);
if ($d =~ /\./) {
my @s = split /\./, $d;
$d = $s[0];
}
foreach my $nm ( ( $low_mid, $mid, $up_mid ) ) {
my $n = ($nm / $i);
if ($n =~ /\./) {
my @s = split /\./, $n;
$n = $s[0];
}
push @{$keys}, $n + $i;
$secret = $secret . $asset[$n + $i] . $asset[$n + $i - 5];
}
$secret = $secret . $numerics[$i - 1];
}
}
}
if ($ass eq '') {
$secret = $sacred;
}
return $secret;
}
post '/sesh_check' => sub ($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $secret = &password_maker($c);
my $reject_count = $c->session('reject_count');
my $start_time = &subs::rightNow();
my $backup = $c->param('president') || $c->param('backup') || $c->param('bullshit');
my $server_time = &subs::rightNow();
my $timestamp = $c->param('timestamp') || &subs::rightNow();
my $remote_timestamp = $c->param('remote_timestamp');
my $me_warranty = &subs::ago_calc(&subs::setting_grabber({ app => 'customs', setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' }) || '-10d');
my $t = localtime;
my $db_exists = 0;
$backup = &subs::home($backup);
my $computer = $c->param('computer');
my $local_address = $c->tx->local_address;
my $remote_address = $c->tx->remote_address;
my $encryption_standard = &subs::setting_grabber({ app => 'misc', setting => 'encryption_standard' } ) || "aes-256-ctr";
if ($backup =~ /enc$/gi) {
my $backup_file = $backup;
$backup_file =~ s/.enc$//gi;
$database = $backup_file . '.db';
unless (-e $database && -s $database > 5000) {
my $data = `tail $backup`;
my @split_data = split $universal_splitter, $data;
$encryption_standard = &subs::decrypter($secret, $split_data[1]);
`openssl enc -d -k "$secret" -$encryption_standard -pbkdf2 -in $backup -out $database`;
}
if (-e $database && -s $database > 5000) {
$sql = Mojo::SQLite->new('sqlite:' . $database);
if (eval { $sql->db }) {
$db_exists = 1;
}
else {
`shred -u $database`;
$db_exists = 0;
}
}
}
elsif ($backup =~ /db$/) {
$database = $backup;
$sql = Mojo::SQLite->new('sqlite:' . $database);
$db_exists = 1;
}
if ($db_exists == 1) {
my ($db,$database) = &subs::database_grabber();
&update_database($c);
# &subs::db_insert('appointments',{ warranty => $me_warranty, uuid => &subs::random_string_creator(40), app => "customs", type => "id", timestamp => $timestamp, server_time => $server_time }) if $db_exists == 1;
my $credential = eval { return &subs::db_select('security', ['credential'], { level => 1 })->hash->{credential} };
$credential = &subs::decrypter($secret,$credential);
if (secure_compare $secret, $credential) {
app->sessions->samesite(undef);
$c->session('authentication' => 'approved');
my $app_warranty = &subs::setting_grabber({ app => $c->param('app'), setting => 'warranty' });
my $warranty = &subs::ago_calc($app_warranty || &subs::setting_grabber({ 'app' => 'me', 'setting' => 'login_warranty' } ) || '-3h',$server_time);
$c->session('database' => $database);
$c->session('suds' => $secret);
$c->session('warranty' => $warranty);
$c->session('string' => &subs::random_string_creator());
$c->session('name') => &subs::setting_grabber({ app => 'me', setting => 'name' });
$c->session('privilege' => 'citizen');
$c->session('app' => $c->param('app'));
my $debbie = eval { return &subs::db_select('settings', ['value'], { app => '__DEBRIEFING__', device => $device })->hash->{value} };
my $deb = $debbie || encode_json [];
my $duration = $start_time - &subs::rightNow();
# &subs::db_insert('appointments',{ warranty => $me_warranty, uuid => &subs::random_string_creator(40), app => "customs", type => "entry", timestamp => $timestamp, server_time => $server_time });
my $d = { title => 'Your Majesty', app => 'customs', role => 'citizen', message => $remote_address, image => "/images/make believe/crown.png" };
unless ($c->param('silence')) {
&subs::say_it('your majesty');
¬ification_sender($d,$database);
}
my $hs = &subs::setting_grabber({ app => 'me', setting => 'computer_name' }) || `hostname`;
chomp $hs;
my $who = `whoami`;
chomp $who;
# my $me = &me_setting_list();
my $colour = '#' . &subs::random_colour_grabber();
my $device_count = &subs::db_query('select count(*) from devices');
my $bti = $c->stash('browser_tab_id');
my $pwd = `pwd`;
chomp $pwd;
my $js = {
'authentication' => 'approved',
hostname => $hs,
username => $who,
debriefer => $deb,
port => $ENV{PORT_AHOY},
ws_port => $ENV{PORT_AHOY},
alarm_port => $ENV{PORT_BELL},
# me => $me,
device => $device,
database => $database,
browser_tab_id => $bti,
manager_file => &manager_file_maker($c->session('name')),
signatorial => &subs::signatorial_designer(),
pwd => $pwd,
fqdn => $config->{'domain'},
ssh_port => $config->{'ssh_port'},
manager_colour => &subs::setting_grabber({ app => 'misc', setting => 'manager_background_colour' })
};
$c->render(json => $js);
}
elsif ($reject_count > 2) {
my $denial = $c->render_to_string(template => 'guest_layouts/denial', message => '... and fuck you too!');
$c->render(json => { 'authentication' => 'denial', denial => $denial });
}
else {
$reject_count = $reject_count + 1;
$c->session('reject_count' => $reject_count);
my $visitor = $local_address eq $remote_address ? 'Me' : $computer || 'door';
&subs::say_it('Who the fuck are you? ' . $visitor . ' ' . $c->session('reject_count'));
&subs::db_insert('appointments',{ warranty => $me_warranty, uuid => &subs::random_string_creator(40), app => "customs", type => "reject", timestamp => $timestamp, server_time => $server_time }) if $db_exists == 1;
$c->render(json => { 'authentication' => 'rejected'});
$c->session('authentication' => 'rejected');
&subs::say_it('I reject: ' . $remote_address);
$c->stash('browser_tab_id' => undef);
$c->session('suds' => 'go fuck yourself');
¬ification_sender({ app => 'customs', role => 'citizen', title => 'WTFAU', message => 'DB open', image => "/images/make believe/explosion.png" },$database);
}
}
else {
my $reject_count = $c->session('reject_count') + 1;
$c->session('reject_count' => $reject_count);
my $visitor = $local_address eq $remote_address ? 'Me' : 'door';
&subs::say_it($c->session('reject_count') . ' Who the fuck are you? ' . $visitor);
$c->render(json => { 'authentication' => 'rejected'});
$c->session('authentication' => 'rejected');
$c->session('suds' => 'fuck you too!');
$c->stash('browser_tab_id' => undef);
¬ification_sender({ app => 'customs', role => 'citizen', title => 'WTFAU', message => 'DB Closed', image => "/images/make believe/explosion.png" },$database);
}
};
get '/manager/debrief_grabber' => sub($c) {
my $ticket_uuid = $c->session('ticket_uuid');
my ($db,$database,$sql) = &subs::database_grabber();
my $q = &subs::db_query('select debriefer from tickets where uuid = ?', $ticket_uuid);
my $debrief = $q->hashes->[0]->{'debriefer'};
my $debriefer = decode_json $debrief || {};
$c->render(json => $debriefer);
};
post '/manager/fuck_you' => sub($c) {
my $timestamp = $c->param('timestamp');
&Websocket::send('server',{ not_me => 1, browser_tab_id => $c->param('browser_tab_id'), 'console' => 'fuck_you();', timestamp => $timestamp });
$c->render('text' => 'fuck yeah!');
};
get '/manager/configure/device_lister' => sub($c) {
my $timestamp = $c->param('timestamp');
my $load_type = $c->param('load_type');
my $ip = $c->param('host');
my $devices = &subs::device_lister($timestamp,$load_type,$ip);
my $ping = &subs::setting_grabber({ app => 'misc', setting => 'ping' });
$c->render(
template => 'configure/device_lister',
devices => $devices,
ping => $ping,
);
};
post '/manager/configure/device_purpose' => sub($c) {
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
my $ip = $c->param('ip');
my $mac = $c->param('mac');
my $uuid = $c->param('uuid');
my $purpose = $c->param('purpose');
my $dev = &subs::db_query('select * from devices where uuid=?',$uuid);
my $devices = $dev->hashes;
foreach my $d ( @{$devices} ) {
my $address = decode_json $d->{'address'};
foreach my $nic ( keys %{$address} ) {
foreach my $neigh ( @{$address->{$nic}->{'neigh'}} ) {
if ($neigh->{'ip'} eq $ip && $neigh->{'mac'} eq $mac) {
$neigh->{'purpose'} = $purpose;
}
}
}
my $json_address = encode_json $address;
&subs::db_update('devices', { address => $json_address }, { uuid => $uuid });
}
$c->render('text' => 'done');
};
get '/manager/time_jump' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $timestamp = $c->param('timestamp');
my $filter = $c->param('filter');
my $type = $c->param('type');
my $app = $c->param('app');
my $scope = $c->param('scope');
my $t = &{$subs::time_subs->{$scope}}($timestamp); #timestamp at beginning
my $t1 = ($timestamp - $t);
my $t2 = ($t1 + $timestamp + $t1);
my $query;
my $date = localtime( time() )->strftime('%a %B %d %Y %I:%M%P');
if ($type eq 'prev') {
if ($filter ne 'all') {
$query = &subs::db_query('select timestamp from appointments where app=? and type=? and timestamp < ? order by timestamp DESC LIMIT 1',
$app,$filter,$t);
}
else {
$query = &subs::db_query('select timestamp from appointments where app=? and timestamp < ? order by timestamp DESC LIMIT 1',
$app,$t);
}
}
elsif ($type eq 'next') {
if ($filter ne 'all') {
$query = &subs::db_query('select timestamp from appointments where app=? and type=? and timestamp > ? order by timestamp ASC LIMIT 1',
$app,$filter,$t2);
}
else {
$query = &subs::db_query('select timestamp from appointments where app=? and timestamp > ? order by timestamp ASC LIMIT 1',
$app,$t2);
}
}
my $res = $query->hashes;
if ($res->[0]->{'timestamp'} == undef) {
$query = &subs::db_query('select timestamp from appointments where app=? and timestamp = ? order by timestamp ASC LIMIT 1',
$app,$timestamp);
$res = $query->hashes;
}
$date = localtime($res->[0]->{'timestamp'} / 1000 )->strftime('%a %B %d %Y %I:%M:%S%P') unless $timestamp == 0 || $timestamp == undef;
$c->render(json => { date => $date, sent_timestamp => $timestamp, new_timestamp => $res->[0]->{'timestamp'} });
};
get '/manager/configure/me_settings' => sub($c) {
my $pos = &subs::setting_grabber({ app => 'me', setting => 'pos' });
my $me = &me_setting_list();
$c->render(
template => 'configure/me_setting_list',
me => $me,
pos_list => $gb::pos
);
};
post '/manager/configure/me_setting' => sub($c) {
my $value = $c->param('value');
if ($value =~ /\%$/gi) {
$value =~ s/\%$//gi;
$value = ($value / 100) + 1;
}
my $setting = &subs::setting_setter({
app => 'me',
setting => $c->param('setting'),
value => $value,
device => $c->param('device'),
timestamp => $c->param('timestamp')
});
$c->render(json => $setting);
};
sub me_setting_list() {
my ($db,$database,$sql) = &subs::database_grabber();
my @settings = qw/mugshot my_name home_plate currency information budget_alarm computer_name unit activity_timeout login_warranty warranty room_count duration worth pos advertise_watching gallery_appts/;
my $settings = {};
foreach my $dt ( @gb::device_types ) {
foreach my $s (@settings) {
my $res = eval {return &subs::db_select('settings', ['value'], { app => 'me', setting => $s, device => $dt })->hash->{value} };
$settings->{$dt}->{$s} = $res;
}
}
return $settings;
}
sub store_setting_list() {
my ($db,$database,$sql) = &subs::database_grabber();
my @settings = qw/store_name slogan logo markup tax address email phone tax_number doc_notes payment_due_date/;
my $settings = {};
foreach my $dt ( @gb::device_types ) {
foreach my $s (@settings) {
my $res = eval {return &subs::db_select('settings', ['value'], { app => 'me', setting => $s, device => $dt })->hash->{value} };
$settings->{$dt}->{$s} = $res;
}
}
return $settings;
}
post '/manager/configure/mugshot_upload' => sub($c) {
my $timestamp = $c->param('timestamp');
my @uploads = @{$c->req->uploads};
my $image;
my $ass;
if (scalar @uploads > 0) {
foreach my $u ( @uploads ) {
$ass = $u->asset->slurp;
$image = 'data:image/png;base64,' . encode_base64($ass);
&subs::setting_setter({ app => 'me', setting => 'mugshot', value => $image });
}
}
$c->render(text => $image );
};
post '/manager/configure/logo_upload' => sub($c) {
my $timestamp = $c->param('timestamp');
my @uploads = @{$c->req->uploads};
my $image;
my $ass;
if (scalar @uploads > 0) {
foreach my $u ( @uploads ) {
$ass = $u->asset->slurp;
$image = 'data:image/png;base64,' . encode_base64($ass);
&subs::setting_setter({ app => 'me', setting => 'logo', value => $image });
}
}
$c->render(text => $image );
};
sub misc_setting_list() {
my ($db,$database,$sql) = &subs::database_grabber();
my @settings = qw/max_files thumbnail_size photo_size max_backups scan_size download_location music_location document_location photo_location video_location encryption_standard scan_location rec_location/;
my $settings = {};
foreach my $dt ( @gb::device_types ) {
foreach my $s (@settings) {
my $res = eval {return &subs::db_select('settings', ['value'], { app => 'misc', setting => $s, device => $dt })->hash->{value} };
$settings->{$dt}->{$s} = $res;
}
}
return $settings;
}
get '/manager/configure/misc_setting_list' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $timestamp = $c->param('timestamp');
my $settings = &misc_setting_list();
my $encryption_standards = `openssl enc -ciphers`;
my @encryption_standards = split ' ', $encryption_standards;
@encryption_standards = map { $_ =~ s/^-//; $_ } @encryption_standards;
shift @encryption_standards;
shift @encryption_standards;
$c->render(
template => 'configure/misc_setting_list',
settings => $settings,
encryption_standards => \@encryption_standards,
photo_sizes => $gb::photo_sizes,
thumbnail_sizes => $gb::thumbnail_sizes,
folders => $config->{'folders'},
config => &subs::config_reader()
);
};
post '/manager/configure/misc_setting' => sub($c) {
&subs::setting_setter({
app => 'misc',
setting => $c->param('setting'),
value => $c->param('value'),
device => $c->param('device'),
timestamp => $c->param('timestamp')
});
$c->render(text => 'ok');
};
get '/manager/configure/ping' => sub($c) {
my $ip = $c->param('host');
my $timestamp = $c->param('timestamp');
my ($db,$database) = &subs::database_grabber();
my $timeout = .2;
my $returner = {};
&subs::setting_setter({ app => 'misc', setting => 'ping', value => $ip });
if ($ip) {
my @ip = split '\.', $ip;
if (scalar @ip == 4) {
$returner->{$ip}->{'ip'} = $ip;
$returner->{$ip}->{'result'} = `timeout $timeout ping -c 1 $ip`;
}
else {
my @ifconfig = split "\n\n", `ifconfig`;
foreach my $if (@ifconfig) {
my @ifconfig_list = split "\n", $if;
my @routes = grep { $_ =~ /inet/ } @ifconfig_list;
foreach my $route (@routes) {
my @inet = split " ", $route;
if ($route =~ /inet /) {
my @items = split " ", $route;
my $sip = $ip;
$sip =~ s/[0-9]//gi;
my $gw = $items[1];
my @gw = split /\./, $gw;
my @csv = split ',', $ip;
if (scalar @csv > 1) {
foreach my $csv (@csv) {
pop @gw;
push @gw, $csv;
my $ip_address = join '.', @gw;
$returner->{$ip_address}->{ip} = $ip_address;
$returner->{$ip_address}->{'result'} = `timeout $timeout ping -c 1 $ip_address`;
}
}
elsif ($sip eq '..' ) {
my @sips = split '\.\.', $ip;
foreach my $csv ( $sips[0] .. $sips[1] ) {
pop @gw;
push @gw, $csv;
my $ip_address = join '.', @gw;
$returner->{$ip_address}->{ip} = $ip_address;
$returner->{$ip_address}->{'result'} = `timeout $timeout ping -c 1 $ip_address`;
}
}
else {
pop @gw;
push @gw, $ip;
my $ip_address = join '.', @gw;
$returner->{$ip_address}->{ip} = $ip_address;
$returner->{$ip_address}->{'result'} = `timeout $timeout ping -c 1 $ip_address`;
}
}
}
}
}
}
$c->render(text => (Dumper $returner) . '
');
};
post '/manager/configure/remote_rsync' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $ip = $c->param('ip');
my $port = $c->param('ssh_port');
my $hostname = `hostname`;
chomp $hostname;
my $direction = $c->param('direction');
my $remote_device = $c->param('device');
my $signatorial = $c->param('signatorial');
my $uuid = $c->param('uuid');
my $home = $c->param('home');
my $folder = $home || '~/president';
my $rm = &subs::db_select('remote_machines', undef, { uuid => $uuid, signatorial => $signatorial, ip => $ip })->hashes;
my $username = $rm->[0]->{'username'};
my $password = &subs::decrypter($c->{'suds'},$rm->[0]->{'password'});
my $connector;
if ($direction eq 'from') {
$connector = 'sshpass -p "' . $password . '" rsync -avr -e "ssh -p ' . $port . '" ' . $username . '@' . $ip . ':' . $home . ' ~/ --delete --exclude=public/images/jonathans --exclude=config.json';
}
elsif ($direction eq 'to') {
$connector = 'sshpass -p "' . $password . '" rsync -avr -e "ssh -p ' . $port . '" ~/president ' . $username . '@' . $ip . ':~/ --delete --exclude=public/images/jonathans --exclude=config.json';
}
my $rest = 'ssh-keyscan -p ' . $port . ' ' . $ip . ' >> ' . &subs::home('~/.ssh/known_hosts');
my $rest_stop = `$rest`;
my $result = `$connector`;
my @result = split "\r", $result;
$result = join "
", @result;
my $whoami = `whoami`;
chomp $whoami;
$connector =~ s/$password/_________/gi;
my $json = { type => 'command', whoami => $whoami, hostname => $hostname, uuid => &subs::random_string_creator(), command => $connector, 'return' => $result, timestamp => $timestamp };
&Websocket::send('server', $json);
&subs::db_update('remote_machines', { server_time => &subs::rightNow(), connection => 'inactive' }, { ip => $ip, uuid => $uuid, signatorial => $signatorial });
$c->render('text' => $result);
};
post '/manager/configure/remote_upgrade' => sub($c) {
if ( &subs::setting_grabber({ app => '__president', setting => 'remote_upgrade' }) eq 'running' ) {
$c->render('text' => 'already running');
$c->rendered;
return;
}
my $timestamp = $c->param('timestamp');
my $ip = $c->param('ip');
my $ssh_port = $c->param('ssh_port');
my $hostname = $c->param('hostname');
my $database = $c->param('database');
my $direction = $c->param('direction');
my $gimme = $c->param('gimme');
my $remote_signatorial = $c->param('signatorial');
my $remote_device = $c->param('device');
my $params = {
timestamp => $timestamp,
ip => $ip,
ssh_port => $ssh_port,
hostname => $hostname,
database => $database,
gimme => $gimme,
remote_signatorial => $remote_signatorial,
remote_device => $remote_device
};
Mojo::IOLoop->subprocess->run_p(sub {
&remote_upgrade($c,$params);
});
$c->render('text' => 'ok');
};
sub remote_upgrade($c,$params) {
if ( &subs::setting_grabber({ app => '__president', setting => 'remote_upgrade' }) eq 'running' ) {
return;
}
&subs::setting_setter({ app => '__president', setting => 'remote_upgrade', value => 'running' });
my $timestamp = $params->{'timestamp'};
my $ip = $params->{'ip'};
my $port = $params->{'ssh_port'};
my $hostname = $params->{'hostname'};
my $database = $params->{'database'};
my $gimme = $params->{'gimme'};
my $remote_signatorial = $params->{'remote_signatorial'};
my $remote_device = $params->{'remote_device'};
my $remote_machine = $params->{'remote_machine'};
my @database = split '/', $database;
my @extender = split /\./, $database[-1];
$extender[-1] = 'enc';
$database[-1] = join '.', @extender;
$database = join '/', @database;
my $folder = '~/';
my $connector;
my $signatorial = &subs::signatorial_designer();
my $download_location = &subs::home('~/.president');
my $temp_folder = &subs::home($download_location . '/' . &subs::random_string_creator(10));
unless ($remote_machine) {
my $remote_machines = &subs::db_query('select * from remote_machines where ip= ? and signatorial = ? order by timestamp DESC', $ip,$remote_signatorial)->hashes;
$remote_machine = $remote_machines->[0];
$remote_machine = &remote_useragent_maker({ ip => $ip, signatorial => $signatorial, rm => $remote_machine });
}
my $auuid = &subs::random_string_creator(10);
if ($remote_machine->{'username'} && $remote_machine->{'password'}) {
my $html = 'Running Remote Backup
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $remote_machine->{'data'}->{'manager_colour'} });
my $url = $remote_machine->{'manager'} . '/manager/configure/backup_now?reason=remote_update×tamp=' . $timestamp . '&signatorial=' . $signatorial;
if ($gimme =~ /[A-Za-z0-9]/gi) {
$gimme = &subs::ago_calc($gimme, &subs::rightNow());
$url .= '&gimme=' . $gimme;
}
else {
$gimme = undef;
}
my $ua = $remote_machine->{'ua'};
my $res = eval { return $ua->insecure(1)->get($url)->result };
if ($res) {
my $body = eval { return decode_json $res->body } || {};
if ($body->{'path'} && $body->{'signatorial'}) {
if (1) {
my $html = 'Syncing Remote Backup ' . &subs::data_size($body->{'size'}) . '
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $remote_machine->{'data'}->{'manager_colour'} });
`mkdir -p $temp_folder` unless -e "$temp_folder";
my $temporary_file = $temp_folder . '/tmpman.enc';
my $username = $remote_machine->{'username'};
my $password = &subs::decrypter($c->session('suds'), $remote_machine->{'password'});
my $connector = 'sshpass -p "' . $password . '" rsync -avr -e "ssh -p ' . $port . '" ' . $username . '@' . $ip . ':' . $body->{'archive_path'} . ' ' . $temporary_file;
my $rest = 'ssh-keyscan -p ' . $port . ' ' . $ip . ' >> ' . &subs::home('~/.ssh/known_hosts');
`$rest`;
my $connected = `$connector`;
my $disposition = &merge_database($c,{
file => $temporary_file,
signatorial => $body->{'signatorial'},
misc_settings => $body->{'misc_settings'},
remote => $remote_machine,
gimme => $gimme,
colour => $remote_machine->{'data'}->{'manager_colour'}
});
`shred -u $temporary_file`;
`rm -R $temp_folder`;
&subs::setting_setter({ app => '__president', setting => 'remote_upgrade', value => '' });
# &subs::db_update('remote_machines', { connection => 'inactive' }, { ip => $ip, signatorial => $remote_machine->{'signatorial'}, uuid => $remote_machine->{'uuid'} });
my $defunct_backups = &subs::db_query('select * from backups where ost < ? and recipient = ? and signatorial = ? and reason=?', $body->{'server_time'}, $signatorial, $remote_machine->{'signatorial'}, 'remote_upgraded' )->hashes;
foreach my $defb ( @{$defunct_backups} ) {
if ($defb->{'enc_file'} && -e $defb->{'enc_file'}) {
my $delb = $defb->{'enc_file'};
`shred -u $delb`;
}
}
&subs::db_query('delete from backups where ost < ? and recipient = ? and signatorial = ? and reason=?', $body->{'server_time'}, $signatorial, $remote_machine->{'signatorial'}, 'remote_upgraded' );
&subs::db_update('backups', { server_time => $body->{'server_time'}, reason => 'remote_upgraded' }, {
recipient => $signatorial,
signatorial => $remote_machine->{'signatorial'},
});
}
}
}
else {
&Websocket::send('tab', { yellow => 'Complete', 'close' => 'yes', colour => $remote_machine->{'data'}->{'manager_colour'} });
}
&Websocket::send('tab', { yellow => 'Complete', 'close' => 'yes', colour => $remote_machine->{'data'}->{'manager_colour'} });
}
}
post '/manager/configure/remote_device_disconnect' => sub ($c) {
my $ip = $c->param('ip');
my ($db,$database,$sql) = &subs::database_grabber();
&subs::db_delete('remote_machines', { ip => $ip });
$c->render('text' => 'ok');
};
get '/manager/configure/remote_device_connect' => sub ($c) {
my $manager = $c->param('manager');
my $filename = $c->param('filename');
my $timestamp = $c->param('timestamp');
my $ip = $c->param('ip');
my $port = $c->param('port');
my $password = $c->session('suds');
my $browser_tab_id = $c->param('browser_tab_id');
my $browser_tab = $c->param('browser_tab');
my $name = $c->session('name');
my $signatorial = $c->param('signatorial');
my $uuid = $c->param('uuid');
my $nic = $c->param('nic');
my $returner = &remote_device_connect({
manager => $manager,
filename => $filename,
timestamp => $timestamp,
ip => $ip,
password => $password,
name => $name,
browser_tab_id => $browser_tab_id,
browser_tab => $browser_tab,
signatorial => $signatorial,
nic => $nic
});
my $device = &subs::db_select('devices', undef, { uuid => $uuid })->hash;
my $address = decode_json $device->{'address'};
my $neighbour = [];
@{$neighbour} = grep { $ip eq $_->{'ip'} } @{$address->{$nic}->{'neigh'}};
$neighbour->[0]->{'signatorial'} = $returner->{'body'}->{'signatorial'};
$neighbour->[0]->{'purpose'} = $returner->{'body'}->{'device'};
$address = encode_json $address;
&subs::db_update('devices', { address => $address }, { uuid => $uuid });
$c->render(json => $returner);
};
sub remote_device_connect($rdata) {
my $manager = $rdata->{'manager'};
my $filename = $rdata->{'filename'};
my $timestamp = $rdata->{'timestamp'};
my $server_time = &subs::rightNow();
my $ip = $rdata->{'ip'};
my $name = $rdata->{'name'};
my $browser_tab_id = $rdata->{'browser_tab_id'};
my $browser_tab = $rdata->{'browser_tab'};
my $password = $rdata->{'password'};
my $port = $rdata->{'port'} || $ENV{PORT_DOCK};
my $nic = $rdata->{'nic'};
my $returner = {};
$manager =~ s/\/manager$//gi;
$manager =~ s/:$port/:3000/gi;
my $bti;
my $ua = Mojo::UserAgent->new();
my $manager_file = &manager_file_maker($name);
my $url = $manager . '/sesh_check?silence=yes&neighbour=' . $browser_tab_id . '&numerics=' . $password . '&president=' . $filename . '&remote_timestamp=' . $timestamp . '&manager_file=' . $manager_file;
my $res = eval { return $ua->insecure(1)->post($url)->result };
$returner->{'body'} = eval { return decode_json $res->body };
$port = $returner->{'body'}->{'port'};
$manager =~ s/:3000/:$port/gi;
$manager =~ s/:6100/:$port/gi;
if ($returner->{'body'}->{'fqdn'} && $ip !~ /[a-zA-Z]/) {
$returner->{'body'}->{'ip_address'} = $ip;
my $fqdn = $returner->{'body'}->{'fqdn'};
my $ping = `timeout .5 ping -c 1 $fqdn`;
if ($ping =~ /ttl/gi) {
my @ping = split /\n/, $ping;
if ($ping[1] =~ /$ip/) {
$manager =~ s/$ip/$fqdn/gi;
my $devices = &subs::db_select('devices')->hashes;
foreach my $d ( @{$devices} ) {
my $address = eval { return decode_json $d->{'address'} };
my @neigh = grep { $_->{'ip'} eq $ip } @{$address->{$nic}->{'neigh'}};
#$neigh[0]->{'ip'} = $fqdn;
$neigh[0]->{'fqdn'} = $fqdn;
$neigh[0]->{'purpose'} = $returner->{'body'}->{'device'};
$neigh[0]->{'ip_address'} = $ip;
$neigh[0]->{'signatorial'} = $returner->{'body'}->{'signatorial'};
my $jaddress = encode_json $address;
&subs::db_update('devices', { address => $jaddress }, { uuid => $d->{'uuid'}} );
}
$ip = $fqdn;
}
}
}
if ($returner->{'body'}->{'authentication'} eq 'approved') {
$ua = Mojo::UserAgent->new();
$url = $manager . '/sesh_check?silence=yes&neighbour=' . $browser_tab_id . '&numerics=' . $password . '&president=' . $filename . '&remote_timestamp=' . $timestamp . '&manager_file=' . $manager_file;
my $double_check = eval { return $ua->insecure(1)->post($url)->result };
$returner->{'body'} = eval { return decode_json $double_check->body } ;
my $signatorial = &subs::signatorial_designer();
if ($returner->{'body'}->{'authentication'} eq 'approved') {# && $returner->{'body'}->{'signatorial'} eq &subs::signatorial_designer()) {
my $uuid = &subs::random_string_creator(15);
$bti = $returner->{'body'}->{'browser_tab_id'};
my $ssh_port = $returner->{'body'}->{'ssh_port'} || $config->{'ssh_port'};
my $remote_device = $returner->{'body'}->{'device'};
my $buttons = [
{ name => 'RD', class => 'neighbour_disconnect', direction => 'disconnect' },
{ name => 'Upgrade', class => 'remote_upgrade' },
{ name => 'cxl_up', class => 'remote_upgrade_clear' },
{ name => '-> Me', class => 'remote_rsync', direction => 'from' },
{ name => 'Me ->', class => 'remote_rsync', direction => 'to' }
];
$returner->{'button'} .= '
';
foreach my $b ( @{$buttons} ) {
$returner->{'button'} .= '';
}
$returner->{'button'} .= '
U:
' .
'P:
' .
'G: ';
$returner->{'status'} = 'Connected';
my $secret = &subs::db_select('security', ['credential'], { level => 1 })->hash->{credential};
my $double = &subs::decrypter($password,$secret);
if ((secure_compare $password, $double)) {
$returner->{'password'} = $secret;
my $hs = `hostname`;
chomp $hs;
$returner->{'hostname'} = $hs;
my $who = `whoami`;
chomp $who;
$returner->{'username'} = $who;
$returner->{'colour'} = '#' . &subs::random_colour_grabber();
#$ua->insecure(1)->get($manager . '/manager/say_it?words=' . &subs::setting_grabber({ app => 'me', setting => 'my_name' }) || $hs)->result;
my $json_buttons = encode_json $buttons;
my $remote_data = encode_json $returner->{'body'};
my $cookie_jar = $ua->cookie_jar;
my @cookies;
for my $cookie (@{$cookie_jar->find(Mojo::URL->new($manager))}) {
push @cookies, {
name => $cookie->name,
value => $cookie->value,
domain => $ip,
path => '/'
};
}
my $cookies = encode_json \@cookies;
my $nd = &subs::db_select('remote_machines', undef, { ip => $ip, signatorial => $returner->{'body'}->{'signatorial'} })->hashes || [];
my $remote_machine = {
ip => $ip,
fqdn => $returner->{'body'}->{'fqdn'},
port => $port,
ws_port => $returner->{'body'}->{'ws_port'},
status => 'connected',
manager => $manager,
timestamp => $timestamp,
server_time => $server_time,
buttons => $returner->{'button'},
data => $remote_data,
signatorial => $returner->{'body'}->{'signatorial'},
cookie => $cookies,
connection => 'active',
uuid => $uuid,
nic => $nic,
manager_file => $returner->{'body'}->{'manager_file'},
device => $returner->{'body'}->{'device'},
hostname => $returner->{'body'}->{'hostname'}
};
if (scalar @{$nd} > 0) {
&subs::db_update('remote_machines', $remote_machine, { ip => $ip, signatorial => $returner->{'body'}->{'signatorial'} });
}
else {
&subs::db_insert('remote_machines', $remote_machine);
}
}
}
}
return $returner;
}
post '/manager/configure/remote_machine_input' => sub($c) {
my $timestamp = $c->param('timestamp');
my $signatorial = $c->param('signatorial');
my $ip = $c->param('ip');
my $uuid = $c->param('uuid');
my $value = $c->param('value');
my $name = $c->param('name');
if ($name eq 'password') {
$value = &subs::encrypter($c->session('suds'), $value);
}
&subs::db_update('remote_machines', { $name => $value }, { ip => $ip, signatorial => $signatorial, uuid => $uuid });
my $remote_machine = &subs::db_select('remote_machines', undef, { ip => $ip, signatorial => $signatorial })->hashes->[0];
$c->render(text => 'ok');
};
post '/manager/configure/remote_device_locker' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $ip = $c->param('ip');
my $status = $c->param('status');
my $nic = $c->param('nic');
my $device = &subs::db_select('devices', undef, { uuid => $uuid })->hashes->[0];
my $address = eval { return decode_json $device->{'address'} };
my @remote_device = grep { $_->{'ip'} eq $ip } @{$address->{$nic}->{'neigh'}};
my $rd = $remote_device[0];
if ($status eq 'yes') {
$rd->{'locked'} = 'no';
}
else {
$rd->{'locked'} = 'yes';
}
@{$address->{$nic}->{'neigh'}} = grep { $_->{'ip'} ne $ip } @{$address->{$nic}->{'neigh'}};
push @{$address->{$nic}->{'neigh'}}, $rd;
@{$address->{$nic}->{'neigh'}} = sort { $a->{'ip'} cmp $b->{'ip'} } @{$address->{$nic}->{'neigh'}};
my $jaddress = encode_json $address;
&subs::db_update('devices', { address => $jaddress }, { uuid => $uuid });
$c->render(json => $rd);
};
sub remote_useragent_maker($data) {
my $ip = $data->{'ip'};
my $signatorial = $data->{'signatorial'};
my $remote_machine = $data->{'rm'};
my $ua = Mojo::UserAgent->new();
$ua = $ua->max_response_size(0);
$remote_machine = &subs::db_select('remote_machines', undef, { ip => $ip, signatorial => $signatorial })->hashes->[0]
unless $remote_machine;
my $manager = $remote_machine->{'manager'};
my $port = $remote_machine->{'port'};
if ($remote_machine->{'cookie'}) {
my $cookie_jar = decode_json $remote_machine->{'cookie'};
foreach my $cookie ( @{$cookie_jar} ) {
$ua->cookie_jar->add(
Mojo::Cookie::Response->new(
name => $cookie->{'name'},
value => $cookie->{'value'},
domain => $cookie->{'domain'},
path => $cookie->{'path'}
)
);
}
my $domain = $config->{'domain'} || $ip;
my $url = 'https://' . $ip . ':3000/manager/remote_auth_test?signatorial=' . &subs::signatorial_designer() . '&domain=' . $config->{'domain'};
$remote_machine->{'ua'} = $ua;
$remote_machine->{'ua'}->inactivity_timeout(3000);
my $res = eval { return $remote_machine->{'ua'}->insecure(1)->get($url => {Accept => '*/*'} => 'Content!')->result };
$remote_machine->{'res'} = $res;
if (!$res) {
$remote_machine->{'ua'} = undef;
}
}
$remote_machine->{'data'} = eval { return decode_json $remote_machine->{'data'} };
return $remote_machine;
}
post '/manager/neighbour_status' => sub($c) {
my $timestamp = $c->param('timestamp');
my $ip = $c->param('ip');
my $status = $c->param('status');
my ($db,$database,$sql) = &subs::database_grabber();
my $remote_machines = &subs::db_query('select * from remote_machines where ip=?', $ip);
my $re_ma = $remote_machines->hashes;
my $rm = $re_ma->[-1];
if ($rm->{'status'} eq 'mirror') {
$rm->{'status'} = 'off';
}
else {
$rm->{'status'} = 'mirror';
}
&subs::db_update('remote_machines', { status => $rm->{'status'} }, { ip => $ip });
$c->render(json => $rm);
my $remote_address = $c->tx->remote_address;
`timeout .5 ping -c 1 $remote_address`;
};
post '/manager/configure/device_domain_updater' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $timestamp = $c->param('timestamp');
my $domain = $c->param('domain');
my $uuid = $c->param('uuid');
&subs::db_update('devices', { 'domain' => $domain }, { timestamp => $timestamp, uuid => $uuid });
$c->render(text => 'ok');
};
post '/manager/configure/device_deleter' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
&subs::db_delete('devices', { timestamp => $timestamp, uuid => $uuid });
$c->render(text => 'deleted');
};
post '/manager/leave' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
&subs::say_it('leave');
&remote_relay_request($c);
my $timestamp = $c->param('timestamp');
$c->param('reason' => 'leave');
my $server_time = &subs::rightNow();
my $d = $c->param('debriefer');
my $settings = decode_json $d;
&subs::db_delete('settings',{app => '__DEBRIEFING__', device => $device});
&subs::db_delete('settings',{app => 'keyboard'});
&subs::db_delete('settings',{app => 'watch', setting => 'patience' });
# &subs::db_delete('remote_machines');
my $hostname = `hostname`;
chomp($hostname);
&subs::db_insert('settings', {
app => '__DEBRIEFING__',
timestamp => $timestamp,
setting => $hostname,
value => $d,
device => $device,
uuid => &subs::random_string_creator(20)
});
my $warranty = &subs::ago_calc(&subs::setting_grabber({ app => 'customs', setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' }) || '-10d', $timestamp);
&subs::db_insert('appointments', { warranty => $warranty, uuid => &subs::random_string_creator(40), app => "customs", type => "depart", timestamp => $timestamp, server_time => $server_time });
# &subs::db_delete('cache');
&subs::backup_now($c);
`shred -u $database`;
`shred -u $database-shm`;
`shred -u $database-wal`;
`shred -u $logfile`;
delete $c->session->{'authentication'};
delete $c->session->{'database'};
delete $c->session->{'suds'};
delete $c->session->{'reject_count'};
delete $c->session->{'browser_tab_id'};
delete $c->session->{'browser_tab'};
my $restore_list;
unless (-e $database && -s $database > 5000) {
$restore_list = &subs::restore_list();
}
$database = '';
my $start_dir = $config->{'start_dir'};
unless (-e $database) {
if ($c->param('restore_list')) {
my $list = $c->param('restore_list');
$restore_list = &subs::restore_list($list);
@{$restore_list} = grep { $_->{'filename'} =~ /enc$/gi } @{$restore_list};
}
}
$c->render(
template => 'gate',
layout => 'gate',
restore_list => $restore_list,
start_dir => $start_dir,
config => { 'gate' => {'background_colour' => 'grey' } },
);
$subs::database_holder = undef;
&subs::say_it('Goodbye');
$sql = undef;
};
post '/manager/lock_session' => sub($c) {
&lock_session($c);
&remote_relay_request($c);
$c->render('text' => 'locked');
};
sub lock_session($c) {
my $now = &subs::rightNow();
my ($db) = &subs::database_grabber();
&subs::setting_setter({ app => '__president', setting => 'pl_time', value => &subs::encrypter($c->session('suds'), $now ) });
if (&subs::setting_grabber({ app => 'gallery', setting => 'combo_unlock' })) {
&subs::setting_deleter({ app => 'gallery', setting => 'combo_unlock' });
&subs::window_closer('gallery');
&subs::setting_deleter({ app => 'music', setting => 'combo_unlock' });
}
my $player = &subs::cache_get({ app => 'music', context => 'player' });
if ($player->{'unlocked'} == 1) {
&subs::cache_delete({ app => 'music', context => 'player' });
&subs::cache_delete({ app => 'music', context => 'content' });
&subs::window_closer('music');
}
my $websockets = &subs::db_query('select * from websockets','stayingAlive')->hashes;
my $port = $c->req->url->base->port;
foreach my $ws ( @{$websockets} ) {
if ($ws->{'href'} =~ /\Q$port/gi) {
my $settings = &subs::settings_grabber({ app => $ws->{'app'}, settings => [ 'visibility' ] });
if ($settings->{'visible'} ne 'checked') {
&subs::window_closer($ws->{'app'});
}
}
elsif (!$ws->{'room'}) {
&subs::db_delete('websockets', { uuid => $ws->{'uuid'} });
}
}
my $padlock = &subs::db_query('select * from security where level = ?', 'padlock')->hashes;
if (scalar @{$padlock} > 0 && $now > $c->session('last_padlock') + 5000) {
my $attempts = &subs::note_decrypter($c->session('suds'), &subs::setting_grabber({ app => '__president', setting => 'padlock_pulls' }));
my $pl = $c->render_to_string(template => 'padlock', mode => 'locker');
my $colour = &subs::random_colour_grabber();
my $taunt_size = scalar @gb::taunts;
my $taunts = $gb::taunts[rand($taunt_size)];
&Websocket::send('server', { padlock => $pl, taunts => $taunts, attempts => $attempts, colour => $colour });
# $c->render(template => 'padlock', mode => 'locker');
# my $path = $c->req->url->path;
# unless $path eq '/manager/security/padlock_pull'
$c->session('last_padlock' => $now );
}
}
get '/manager' => sub ($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $hostname = `hostname`;
chomp $hostname;
sub jonathan_to_jawn() {
my $jonathans = `ls images/jonathans`;
my @jonathans = split "\n";
my @jawns = [];
foreach my $jonathan ( @jonathans ) {
push @jawns, {
file => $jonathan
};
}
}
my $advertise_watching = &subs::setting_grabber({ app => 'me', setting => 'advertise_watching' });
my $pseudonyms = &pseudonym_maker('manager','');
my $phtml = $c->render_to_string(
template => 'pseudonyms',
config => &subs::config_reader(),
pseudonyms => $pseudonyms,
device => $device
);
my ($website,$header) = &website_preloader($c);
my $my_name = &subs::setting_grabber({ app => 'me', setting => 'my_name' });
my $ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/manager/ws';
my $mail_ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/mail/ws';
my $paperboy_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/observer/ws';
my $padlock = &subs::db_select('security', ['level'], { level => 'padlock' })->hashes;
my $parking_lot = &parking_lot_grabber($c);
$c->render(
pseudonyms => $pseudonyms,
bar => $phtml,
layout => 'manager',
title => &subs::setting_grabber({ app => 'me', setting => 'computer_name' }) || $hostname,
template => 'manager',
newsstand => &subs::statement_grabber(),
manager_file => &manager_file_maker($c->session('name')),
config => &subs::config_reader(),
website => $website,
my_name => $my_name,
'device' => $device,
'ws_url' => $ws_url,
mail_ws_url => $mail_ws_url,
paperboy_url => $paperboy_url,
advertise_watching => $advertise_watching,
padlock => $padlock,
header => $header,
menu => 'running'
);
};
get '/manager/window_retriever' => sub($c) {
my $ticket_uuid = $c->session('ticket_uuid');
my $user_agent = $c->param('user_agent');
my $wsq = &subs::db_query('select distinct(app) as app,* from websockets where ticket_uuid = ? and user_agent = ? order by server_time desc LIMIT 20', $ticket_uuid, $user_agent)->hashes;
my @actuals = grep { $_->{'browser_tab_id'} eq $c->param('browser_tab_id') } @{$wsq};
if (scalar @actuals > 0) {
@{$wsq} = @actuals;
}
my $returner = { 'tab' => {}, 'server' => {}, 'music' => {} };
foreach my $ws ( @{$wsq} ) {
if ( $ws->{'app'} eq 'tab' && $ws->{'windows'}) {
$returner->{$ws->{'app'}} = $ws;
}
}
$c->render(json => $returner);
};
get '/manager/start_menu' => sub($c) {
my $start_menu = &start_menu_maker($c);
$c->render(json => $start_menu);
};
sub start_menu_maker($c) {
my $fingerprint = 0;
my $returner = {};
my $menu = $c->param('menu');
if (1 == 0) {
&Websocket::send('server', { console => '$(\'#alert\').html(\'Fingerprint NOW!
\').show()' });
if ($device eq 'mobile') {
my $tf = `termux-fingerprint`;
my $f = eval { return decode_json $tf } || {};
if ($f->{'auth_result'} eq 'AUTH_RESULT_SUCCESS') {
$fingerprint = 1;
}
}
elsif ($device eq 'computer' ) {
my $f = `fprintd-verify`;
my @f = split /\n/, $f;
if ($f[-1] eq 'Verify result: verify-match (done)') {
$fingerprint = 1;
}
}
else {
$fingerprint = 1;
}
&Websocket::send('server', { console => '$(\'#alert\').hide()' });
}
$fingerprint = 1;
if ($fingerprint == 1) {
$returner = {
html => $c->render_to_string(
template => 'start_menu',
parking_lot => &parking_lot_grabber($c),
config => &subs::config_reader(),
padlock => &subs::db_select('security', ['level'], { level => 'padlock' })->hashes,
menu => $menu
)
};
}
else {
&lock_session($c);
}
return $returner;
}
sub parking_lot_grabber($c) {
my $parking_lot = {};
my $spaces = &subs::db_query('select * from websockets where room is not null')->hashes;
foreach my $pl ( @{$spaces} ) {
my $others = &subs::db_select('websockets', undef, { browser_tab_id => $pl->{'browser_tab_id'} })->hashes;
foreach my $ot ( @{$others} ) {
if ($ot->{'music_data'}) {
$pl->{'music_data'} = $ot->{'music_data'};
}
elsif ($ot->{'jp_data'}) {
$pl->{'jp_data'} = $ot->{'jp_data'};
}
}
$parking_lot->{$pl->{'room'}} = $pl;
}
return $parking_lot;
}
sub website_preloader($c) {
my ($website,$header);
if ($c->param('app')) {
my $advertise_watching = &subs::setting_grabber({ app => 'me', setting => 'advertise_watching' });
my $app = $c->param('app');
$header = &subs::appt_header_printer({ app => $app });
my $timestamp = $c->param('timestamp') || &subs::rightNow();
my $appts = &log_reader({ app => $app, view => 'centre_view', timestamp => $timestamp });
$website = $c->render_to_string(
template => 'appointment_wrapper',
appts => $appts,
appointments => [ $app ],
timestamp => $timestamp,
device => $device,
from => 'centre_view',
config => &subs::config_reader(),
measures => $gb::measures,
advertise_watching => $advertise_watching,
header => $header
);
$website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => $app, contents => $website }, $timestamp);
$c->stash('website' => $website);
}
return ($website,$header);
}
sub pseudonym_maker($context,$app) {
if (my $ps = &subs::cache_get({ app => 'me', context => 'pseudonyms', subcontext => $context })) {
return $ps;
}
my $pseudonyms = [
{ status => 'on', name => "remote_control", icon => "Froggoli", speech => 'Ribbit' },
{ status => 'on', name => "delorean", icon => "Mr. Sun", speech => 'Run for it Marty!' },
{ status => 'on', name => "walkboy", icon => "headphones", speech => 'av room' },
{ status => 'on', name => "keyboard", icon => "keyboard", speech => 'typewriter' },
{ status => 'on', name => "calculator", icon => "calculator", speech => 'calculator' },
{ status => 'on', name => "notifications", icon => "bell", speech => 'where are your friends now?' },
{ status => 'on', name => "console", icon => "windows", speech => 'i watch the baytch' },
{ status => 'on', name => "controller", icon => "heart", speech => 'Run for it Marty!' },
{ status => 'button', name => 'record', icon => 'record', classmates => "medium_thumb save_appointment", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'text', icon => 'love letter', colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'start', icon => 'play', classmates => "medium_thumb save_appointment", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'prev', icon => 'prev', classmates => "medium_thumb time_jump", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'next', icon => 'next', classmates => "medium_thumb time_jump", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'stop', icon => 'stop', classmates => "medium_thumb save_appointment", click => "", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'note', icon => 'Mr. President', classmates => "br medium_thumb save_appointment", colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'msg', icon => 'mailbox', colour => '#ffec1f', place => 'top' },
{ status => 'button', name => 'usual', icon => 'usual_button', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'video', icon => 'camera', classmates => "little_thumb multimedia save_appointment", click => "", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'camera', icon => 'eye', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'marker', icon => 'marker', colour => '#ff0000', place => 'mid' },
{ status => 'button', name => 'screen', icon => 'monitor', classmates => "little_thumb multimedia save_appointment", click => "", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'audio', icon => 'microphone', classmates => "little_thumb save_appointment", click => "", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'renew', icon => 'renew', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'cancel', icon => 'cancel_button', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'telephone', icon => 'telephone line', classmates => 'medium_thumb save_appointment', colour => '#ffec1f', place => 'mid' },
{ status => 'button', name => 'delay', icon => 'delay_button', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'transaction', icon => 'register', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'complete', icon => 'cake', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'inventory', icon => 'inventory', classmates => "little_thumb", colour => '#bdd6c5' },
{ status => 'button', name => 'upload', icon => 'upload', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'entry', icon => 'eye', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'dingaling', icon => 'badge', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'id', icon => 'key', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'backup', icon => 'diskette', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'image', icon => 'gallery', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'leave', icon => 'exit', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'snapshot', icon => 'gallery', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'studio', icon => 'mixer', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'purchase', icon => 'cash', colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'pause', icon => 'pause', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'resume', icon => 'detour', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'mid' },
{ status => 'button', name => 'command', icon => 'code', classmates => "little_thumb save_appointment", colour => '#ff007b', place => 'bottom' },
{ status => 'button', name => 'sms', icon => 'phone_sms', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'bottom' },
{ status => 'button', name => 'scan', icon => 'flatbed', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'bottom' },
{ status => 'button', name => 'feeder', icon => 'feeder', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'bottom' },
{ status => 'button', name => 'scraper', icon => 'scraper', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'none' },
{ status => 'button', name => 'config', icon => 'wrench', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'none' },
{ status => 'button', name => 'web', icon => 'web_button', classmates => "little_thumb save_appointment", colour => '#bdd6c5', place => 'bottom' },
{ status => 'cursor', name => 'pointer', icon => 'pointer', classmates => "little_thumb", colour => '#ffec1f', place => 'bottom' },
{ status => 'cursor', name => 'eyepointer', icon => 'eyepointer', classmates => "little_thumb", colour => "#ffec1f", place => 'bottom' },
{ status => 'cursor', name => 'measure', icon => 'measures', classmates => "little_thumb", colour => "#ffec1f", place => 'bottom' },
];
my $custom_pseudonyms = eval { return decode_json &subs::setting_grabber({ 'app' => 'config', setting => 'pseudonyms' }) } || {};
if ($context eq 'manager') {
@{$pseudonyms} = grep { $_->{'status'} eq 'on' } @{$pseudonyms};
}
elsif ($context eq 'config') {
@{$pseudonyms} = grep { $_->{'status'} eq 'on' || $_->{'status'} eq 'off' } @{$pseudonyms};
}
elsif ($context eq 'viewer') {
#@{$pseudonyms} = grep { $_->{'status'} eq 'button' } @{$pseudonyms};
}
elsif ($context eq 'store') {
@{$pseudonyms} = grep { $_->{'classmates'} !~ /save_appointment/ } @{$pseudonyms};
}
elsif ($context eq 'teletype') {
@{$pseudonyms} = grep { $_->{'status'} eq 'cursor' } @{$pseudonyms};
}
foreach my $p ( @{$pseudonyms} ) {
foreach my $k ( keys %{$custom_pseudonyms->{$p->{'name'}}} ) {
$p->{$k} = $custom_pseudonyms->{$p->{'name'}}->{$k} if $custom_pseudonyms->{$p->{'name'}}->{$k};
}
unless ( $custom_pseudonyms->{$p->{'name'}}->{'icon'} ) {
my $i = $p->{'icon'};
$p->{'icon'} = "/images/decipherable/" . $i . ".png";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/images/studio/" . $i . ".png";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/images/make believe/" . $i . ".png";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/icons/" . $i . ".png";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/icons/" . $i . ".jpg";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/images/icons/" . $i . ".png";
unless (-e "public/" . $p->{'icon'}) {
$p->{'icon'} = "/images/jonathans/" . $i . ".png";
}
}
}
}
}
}
}
}
&subs::cache_set({ app => 'me', context => 'pseudonyms', subcontext => $context }, $pseudonyms);
return $pseudonyms;
};
get '/manager/configure/pseudonym_list' => sub($c) {
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
my $pseudonyms = &pseudonym_maker('','');
$c->render(
template => '/configure/pseudonym_list',
pseudonyms => $pseudonyms
);
};
post '/manager/configure/pseudonym_setter' => sub($c) {
my $timestamp = $c->param('timestamp');
&subs::cache_delete({ app => 'me', context => 'pseudonyms' });
my $custom_pseudonyms = eval { return decode_json &subs::setting_grabber({ app => 'config', setting => 'pseudonyms' }) } || {};
my $setting = $c->param('setting');
my $name = $c->param('name');
my $value = $c->param('value');
$custom_pseudonyms->{$name}->{$setting} = $value;
my $cs = encode_json $custom_pseudonyms;
&subs::setting_setter({ app => 'config', setting => 'pseudonyms', value => $cs });
my $pseudonyms = &pseudonym_maker('','');
$c->render(
template => '/configure/pseudonym_list',
pseudonyms => $pseudonyms
);
};
get '/manager/configure/pseudonym_defaulter' => sub($c) {
my $name = $c->param('name');
my $custom_pseudonyms = eval { return decode_json &subs::setting_grabber({ app => 'config', setting => 'pseudonyms' }) } || {};
$custom_pseudonyms->{$name} = undef;
my $cs = encode_json $custom_pseudonyms;
&subs::setting_setter({ app => 'config', setting => 'pseudonyms', value => $cs });
my $pseudonyms = &pseudonym_maker('','');
$c->render(
template => '/configure/pseudonym_list',
pseudonyms => $pseudonyms
);
};
post '/manager/configure/pseudonym_icon_changer' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $custom_pseudonyms = eval { return decode_json &subs::setting_grabber({ app => 'config', setting => 'pseudonyms' }) } || {};
my $name = $c->param('name');
my $image = $c->param('image');
$custom_pseudonyms->{$name}->{'icon'} = $image;
my $cs = encode_json $custom_pseudonyms;
&subs::setting_setter({ app => 'config', setting => 'pseudonyms', value => $cs });
my $pseudonyms = &pseudonym_maker('','');
my $returner;
$returner->{'list'} = $c->render_to_string(
template => '/configure/pseudonym_list',
pseudonyms => $pseudonyms
);
$c->render(json => $returner);
};
get '/manager/qrcode_generator' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $name = &subs::unformat_name($c->param('name') || 'visitor');
my $privilege = $c->param('privilege') || 'visitor';
my $project = $c->param('project');
my $debriefer = $c->param('debriefer');
my $nic = $c->param('nic');
my $server_time = &subs::rightNow();
my ($db,$database,$sql) = &subs::database_grabber();
my $random_password = &subs::random_string_creator(40);
my $sj = { ts => $timestamp, p => &subs::random_string_creator(25), uuid => &subs::random_string_creator(10) };
my $secret_json = encode_json $sj;
my $suds = &subs::note_encrypter($sj->{'p'}, $c->session('suds'));
my $secret = &subs::note_encrypter($random_password, $secret_json);
$secret = url_escape `echo "$secret" | base64 -w 0`;
my $uuid = $sj->{'uuid'};
my $domain;
if ($nic eq &subs::config_reader()->{'domain'}) {
$domain = $nic;
}
else {
my $x = &subs::device_lister($timestamp, '')->[0]->{'address'};
$domain = $x->{$nic}->{'ip'};
}
my $port = $ENV{PORT_AHOY};
if ($device eq 'server') {
$port = 443;
}
my $url = 'https://' . $domain . ':' . $ENV{'PORT_DOCK'} . '/box_office/' . $sj->{'uuid'} . '?s=' . $secret;
my $warranty = $c->param('warranty') || &subs::setting_grabber({ app => 'box_office', setting => 'warranty' });
&subs::setting_setter({ app => 'box_office', setting => 'warranty', value => $warranty });
$warranty = &subs::ago_calc($warranty,$timestamp);
my $duration = $warranty - $timestamp;
&appointment_writer($c,{
app => 'name',
project => $project,
timestamp => $timestamp,
warranty => $warranty
});
my $qr = `qrencode -o - $url`;
my $image = 'data:image/png;base64,' . encode_base64($qr);
my $data = {
timestamp => $timestamp,
uuid => $sj->{'uuid'},
warranty => $warranty,
url => $url,
server_time => $server_time,
name => $name,
image => $image,
privilege => $privilege,
verification => $secret,
status => 'active',
duration => $duration,
app => $app,
password => $random_password,
port => $ENV{PORT_AHOY},
ip => $domain,
secret => $secret,
nic => $nic,
project => $project,
suds => $suds,
debriefer => $debriefer
};
&subs::db_insert('tickets', $data);
&subs::setting_setter({ app => 'box_office', setting => 'last_privilege', value => $privilege });
&subs::setting_setter({ app => 'box_office', setting => 'last_nic', value => $nic });
&subs::setting_setter({ app => 'box_office', setting => 'last_name', value => $name });
$c->render(json => $data);
};
sub qrcode_updater($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $timestamp = $c->param('timestamp');
my $q = &subs::db_query('select * from tickets');
my $tickets = $q->hashes;
my $level_one_q = &subs::db_query('select timestamp from security where level=1 order by timestamp DESC limit 1');
my $level_one = $level_one_q->hashes;
foreach my $t ( @{$tickets} ) {
my $secretive = $t->{'secret'};
my $ver = url_unescape `echo "$secretive" | base64 --decode`;
my $ts = &subs::note_decrypter($t->{'password'},$ver);
my $sj = decode_json $ts;
if ( $t->{'port'} ne $ENV{PORT_AHOY} || $level_one->[0]->{'timestamp'} >= $t->{'server_time'}) {
# $sj->{'ts'} = &subs::rightNow();
my $suds = &subs::note_encrypter($sj->{'p'}, $c->session('suds'));
my $secret_json = encode_json $sj;
my $secret = &subs::note_encrypter($t->{'password'}, $secret_json);
$secret = url_escape `echo "$secret" | base64 -w 0`;
my $x = &subs::device_lister($timestamp, '')->[0]->{'address'};
my $url = 'https://' . $x->{$t->{'nic'}}->{'ip'} . ':' . $ENV{'PORT_DOCK'} . '/box_office/' . $t->{'uuid'} . '?s=' . $secret;
my $qr = `qrencode -o - $url`;
my $image = 'data:image/png;base64,' . encode_base64($qr);
&subs::db_update('tickets', {
ip => $x->{$t->{'nic'}}->{'ip'},
# url => $url,
# image => $image,
port => $ENV{PORT_AHOY},
server_time => &subs::rightNow(),
# secret => $secret,
suds => $suds
},
{ uuid => $t->{'uuid'} });
}
}
}
get '/manager/box_office' => sub($c) {
my $app = &subs::unformat_name('box_office');
my $view = $c->param('view') || &subs::setting_grabber({ app => 'misc', setting => 'box_office_view' });
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
&qrcode_updater($c);
my $ticks = &subs::db_query('select * from tickets');
my $tickets = $ticks->hashes;
my $devices = &subs::device_lister($timestamp, '');
my $addresses = $devices->[0]->{'address'};
my $warranty = $c->param('warranty') || &subs::setting_grabber({ app => $app, setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' });
my $projs = &subs::db_query('select * from settings where setting=? and value=?', 'pos','project');
my $projects = $projs->hashes;
my $persons = &subs::db_query('select * from settings where setting=? and value=? or value = ?', 'pos','person', 'customer');
foreach my $t ( @{$tickets} ) {
my $al = eval { return decode_json $t->{'access_log'} } || [];
$t->{'access_log'} = $al;
}
my $people = $persons->hashes;
my $content = $c->render_to_string(
template => 'box_office',
timestamp => $timestamp,
config => &subs::config_reader(),
addresses => $addresses,
tickets => $tickets,
nic => &subs::setting_grabber({ app => $app, setting => 'last_nic' }),
name => &subs::setting_grabber({ app => $app, setting => 'last_name' }) || &subs::setting_grabber({ app => 'me', setting => 'my_name' }),
privilege => &subs::setting_grabber({ app => $app, setting => 'last_privilege' }) || 'visitor',
warranty => $warranty,
projects => $projects,
people => $people,
config => &subs::config_reader(),
view => $view
);
if ($c->param('source') ne 'list') {
$content = &window_maker({ user_agent => $c->param('user_agent'), app => $app, contents => $content }, $timestamp);
}
$c->render('text' => $content);
};
any '/box_office/ticket_request' => sub($c) {
my $call = $c->param('call');
my $privilege = $c->param('privilege');
my $team = $c->param('team');
my $club = $c->param('club');
my $community = $c->param('community');
my $timestamp = $c->param('timestamp');
if ($call eq 'form') {
my $content = $c->render_to_string(
template => 'store/ticket_request',
);
$c->render(json => { content => $content });
}
elsif ($call eq 'privilege') {
my $content = $c->render_to_string(
template => 'store/ticket_request_privilege',
privilege => $privilege,
team => $team,
club => $club,
community => $community
);
$c->render(json => { content => $content });
}
elsif ($call eq 'submit') {
my ($db) = &subs::database_grabber();
my $data = eval { return decode_json $c->param('data') };
if ($data->{'approval_rating'}) {
&subs::db_insert('tickets', {
name => &subs::unformat_name($data->{'name'}),
timestamp => $timestamp,
server_time => &subs::rightNow(),
information => $c->param('data')
});
}
}
else {
$c->render(template => 'guest_layouts/denial');
}
};
get '/box_office/:uuid' => sub($c) {
my $uuid = $c->stash('uuid');
my $secret = $c->param('s');
my $ip = $c->tx->remote_address;
my $server_time = &subs::rightNow();
my $timestamp = $c->param('timestamp') || $server_time;
my ($db,$database) = &subs::database_grabber();
my $base_host = $c->req->url->base->host;
if ($base_host ne $config->{'domain'} && $ip ne $c->tx->local_address) {
$c->render(template => 'guest_layouts/denial');
return;
}
my $base_url = 'https://' . $base_host . ':' . $ENV{PORT_AHOY};
unless ($db) {
$c->redirect_to($base_url . '/manager');
return;
}
my $tick = &subs::db_query('select * from tickets where uuid=?', $uuid);
my $ticke = $tick->hashes;
unless (scalar @{$ticke} > 0) {
$c->redirect_to($base_url . '/manager');
return;
}
my $ticket = $ticke->[0];
my $access_log = eval { return decode_json $ticket->{'access_log'} } || [];
my $access = { server_time => $server_time, status => 'denial', ip => $ip };
my $v = $ticket->{'verification'};
my $ver = url_unescape `echo "$secret" | base64 --decode`;
my $verification = &subs::note_decrypter($ticket->{'password'}, $ver) ;
my $vrai = eval { return decode_json $verification } || {};
unless ($vrai->{'p'}) {
$c->redirect_to($base_url . '/manager');
return;
}
$secret = &subs::decrypter($vrai->{'p'},&subs::db_select('security', ['credential'], { level => 1 })->hash->{credential});
my $suds = &subs::note_decrypter($vrai->{'p'}, $ticket->{'suds'});
chomp $suds;
if ((secure_compare $secret, $suds) && $ticket->{'privilege'} && $ticket->{'status'} eq 'active') {
&update_database($c);
$c->session('role' => $ticket->{'privilege'});
my $warranty = &subs::ago_calc(&subs::setting_grabber({ 'app' => $ticket->{'name'}, setting => 'warranty' }), $timestamp);
#&subs::db_insert('appointments',{ uuid => &subs::random_string_creator(40), app => $ticket->{'name'}, warranty => $warranty, type => "entry", timestamp => $timestamp, server_time => $server_time });
my $d = { app => 'customs', role => 'citizen', title => 'Your Majesty', message => &subs::format_name($ticket->{'privilege'}) . ': ' . &subs::format_name($ticket->{'name'}), image => "/images/make believe/crown.png" };
$c->session('database' => $database);
$c->session('authentication' => 'approved');
$c->session('suds' => $suds);
$c->session('server_time' => $server_time);
$c->session('warranty' => $ticket->{'warranty'});
$c->session('source' => 'ticket');
$c->session('ticket_uuid' => $ticket->{'uuid'});
$c->session('name' => $ticket->{'name'});
$c->session('privilege' => $ticket->{'privilege'});
$c->session('project' => $ticket->{'project'});
$c->session('app' => $ticket->{'app'} );
$c->session('padlock' => $server_time) if (scalar @{&subs::db_select('security', [ 'level' ], { level => 'padlock' })->hashes} > 0);
unless ($c->req->url->base->port eq 3000) {
&subs::say_it($ticket->{'name'});
¬ification_sender($d,$database);
}
$access->{'status'} = 'approved';
my $mail_ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/mail/ws';
my $image = $gb::known_appts->{$ticket->{'privilege'}}->{'icon'};
my %js = (
title => 'Box Office',
layout => 'gate',
template => 'guest_layouts/box_office',
'authentication' => 'approved',
port => $ENV{PORT_AHOY},
ws_port => $ENV{PORT_MSG},
alarm_port => $ENV{PORT_BELL},
device => $device,
manager_file => &manager_file_maker($c->session('name')),
ticket => $ticket,
image => $image
);
my $msg = encode_json { app => 'server', ticket => $ticket, timestamp => $timestamp };
if ($ticket->{'privilege'} eq 'citizen') {
$js{'redirector'} = $base_url . '/manager';
$js{'debriefer'} = $ticket->{'debriefer'};
$js{'js'} = encode_json \%js;
$c->render(%js);
}
elsif ($ticket->{'privilege'} eq 'resident') {
$js{'debriefer'} = $ticket->{'debriefer'};
$js{'redirector'} = $base_url . '/store?app=' . $ticket->{'app'};
$js{'js'} = encode_json \%js;
$c->render(%js);
}
elsif ($ticket->{'privilege'} eq 'guest') {
$js{'redirector'} = $base_url . '/';
# $js{'debriefer'} = $deb;
$js{'js'} = encode_json \%js;
$c->render(%js);
}
}
else {
$c->render(template => 'guest_layouts/denial');
}
unless ( grep { $_->{'server_time'} >= $server_time - 5000 } @{$access_log} ) {
unshift @{$access_log}, $access;
splice @{$access_log}, 20;
$ticket->{'access_log'} = encode_json $access_log;
$ticket->{'server_time'} = &subs::rightNow();
&subs::db_update('tickets', $ticket, { uuid => $ticket->{'uuid'} });
}
};
get '/manager/delete_ticket' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my ($db,$database,$sql) = &subs::database_grabber();
&subs::db_delete('tickets', { uuid => $uuid });
$c->render('json' => { uuid => $uuid });
};
get '/manager/suspend_ticket' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my ($db,$database,$sql) = &subs::database_grabber();
&subs::db_query('update tickets set status=? where uuid=?','suspended',$uuid);
$c->render('json' => { uuid => $uuid });
};
get '/manager/renew_ticket' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $warranty = $c->param('warranty');
my ($db,$database,$sql) = &subs::database_grabber();
my $tick = &subs::db_query('select * from tickets where uuid=?', $uuid);
my $ticke = $tick->hashes;
my $ticket = $ticke->[0];
$warranty = &subs::ago_calc($warranty,$timestamp);
my $total_duration = ($warranty - $ticket->{'timestamp'});
my $new_warranty = ($ticket->{'duration'} + $timestamp);
&subs::db_update('tickets', { status => 'active', duration => $total_duration, warranty => $warranty }, { uuid => $uuid });
$c->render('json' => $ticket);
};
get '/manager/reinstate_ticket' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my ($db,$database,$sql) = &subs::database_grabber();
my $data = { status => 'active' };
&subs::db_update('tickets', $data, { uuid => $uuid });
$c->render('json' => $data);
};
get '/manager/random_word' => sub ($c) {
my $rw = &random_word_grabber($c->param('times'));
$c->render( text => $rw );
};
sub random_word_grabber($times) {
$times = $times || 2;
my ($db,$database,$sql) = &subs::database_grabber();
my $sentence;
for (my $t = 0; $t <= $times; $t++) {
my $labour = '%';
foreach my $n ( 0..3 ) {
my $r1 = &subs::random_string_creator(100);
$r1 =~ s/[^0-9]//gi;
my @r2 = split "", $r1;
$labour .= $r2[0] . '%';
}
$labour .= '%';
my $query = &subs::db_query('select app from appointments where timestamp like ? LIMIT 50', $labour);
my $apps = $query->hashes;
my @words;
foreach my $a ( @{$apps} ) {
my @split = shuffle split '_', $a->{'app'};
foreach my $sp ( @split ) {
push @words,$sp if $sp !~ /[^a-zA-z]/;
}
}
@words = shuffle @words;
$sentence .= $words[rand(50)];
$sentence .= ' ' if $times > 1;
}
return $sentence;
};
sub original_timestamp() {
my ($db,$database,$sql) = &subs::database_grabber();
my $original_timestamp = &subs::db_query('select timestamp from security LIMIT 1');
my $ts = $original_timestamp->hashes;
return $ts->[0]->{'timestamp'} ;
}
sub log_reader {
my $data = $_[0] || {};
my ($db,$database,$sql) = &subs::database_grabber();
my $chosen_app = $data->{'app'};
my $scope = $data->{'scope'};
my $timestamp = $data->{'timestamp'};
my $timeshift_max = $data->{'timeshift_max'};
my $search = $data->{'search'};
my $stats = $data->{'stats'};
#my $misc_settings = &misc_setting_list();
my $open_appts = $data->{'appts'};
my $appt_toggle = $data->{'appt_view_toggle'};
my $sorts = $data->{'sorts'};
my $account = $data->{'account'};
my $project = $data->{'project'};
my $timestamp_selector = $data->{'sorts'} || 'timestamp';
$timestamp_selector = 'timestamp' if $timestamp_selector eq 'occurrences';
if ($sorts eq 'server_time') {
$timestamp_selector = 'server_time';
}
my $time_definition = &subs::rightNow();
my $server_time = $time_definition;
# $time_definition = $timestamp unless $timestamp_selector eq 'server_time';
undef @appointments;
my ($results,$appointments);
my $original_timestamp = &subs::db_query('select timestamp from security LIMIT 1');
my $ts = $original_timestamp->hashes;
my $birthday = &subs::duration_sayer( ($timestamp / 1000 ) - &subs::ago_calc( $config->{'birthday'},$timestamp) / 1000) || (($timestamp / 1000 ) - (&original_timestamp() / 1000 ) );
my $json;
my $jdata = encode_json $data;
my $appts = {
'__specs' => {
birthday => $birthday,
timestamp => $timestamp,
formatted_timestamp => localtime($timestamp / 1000 )->strftime('%a %D %I:%M:%S%P'),
server_time => &subs::rightNow(),
data => $jdata
},
'__params' => $data,
};
if ($scope && $timestamp && $data->{'view'} eq 'appointment_viewer') {
# appointment_viewer
my $t = &{$subs::time_subs->{$scope}}($timestamp); #timestamp at beginning
my $t1 = ($timestamp - $t);
my $t2 = ($t1 + $timestamp + $t1);
$appts->{'__specs'}->{'start'} = $t;
$appts->{'__specs'}->{'end'} = $t2;
if ($appt_toggle eq 'on') {
my $temp_appointments;
foreach my $a (@{$open_appts}) {
my @query_variables = ( $a, $t, $t2 );
my $query;
if ($data->{'filter'} && $data->{'filter'} ne 'all') {
$query = "select timestamp,app,server_time,type,duration from appointments where app = ? AND $timestamp_selector between ? and ? and type = ?";
push @query_variables, $data->{'filter'};
}
else {
$query = "select timestamp,app,server_time,type,duration from appointments where app = ? AND $timestamp_selector between ? and ?";
}
if ($project && $project ne 'all') {
$query .= " and project = ? ";
push @query_variables, $project;
}
if ($account && $account ne 'all') {
$query .= " and account = ? ";
push @query_variables, $account;
}
$query .= " order by $timestamp_selector";
$results = &subs::db_query($query, @query_variables);
$temp_appointments = $results->hashes;
push @{$appointments}, @{$temp_appointments};
}
}
else {
my $query;
my @query_variables = ( $t, $t2 );
if ($data->{'filter'} && $data->{'filter'} ne 'all') {
$query = "select distinct(app) as app,* from appointments where $timestamp_selector between ? and ? and type = ?";
push @query_variables, $data->{'filter'};
}
else {
$query = "select distinct(app) as app,* from appointments where $timestamp_selector between ? and ?";
}
if ($project && $project ne 'all') {
$query .= " and project = ? ";
push @query_variables, $project;
}
if ($account && $account ne 'all') {
$query .= " and account = ? ";
push @query_variables, $account;
}
$query .= " order by $timestamp_selector LIMIT 500";
$results = &subs::db_query($query, @query_variables);
$appointments = $results->hashes;
}
# my $resulters = &subs::db_query('select * from continent where timestamp >= ? and timestamp <= ?',$t,$t2);
my $continent = [];#$resulters->hashes;
my ($last,$next);
my $n = 0;
foreach my $con ( @{$continent }) {
$n = $n + 1;
my $last = $continent->[$n - 1];
my $next = $continent->[$n + 1];
if ($con->{'latitude'} ) {
push @{$appts->{'__continent'}}, { latitude => $con->{'latitude'}, longitude => $con->{'longitude'} };
}
}
}
elsif ($search) {
#search
my @search_split = split ' ', $search;
my $searchable = join '%', @search_split;
my $s = "%" . $searchable . "%";
$results = &subs::db_query('select * from appointments where app like ?', $s);
my $temp_appointments = $results->hashes;
my (@n,@perfect_n);
foreach my $a (reverse @{$temp_appointments}) {
if ($a->{'app'} eq $searchable) {
unshift @n, $a unless grep { $_->{'app'} eq $a->{'app'} } @n;
}
else {
push @n, $a unless grep { $_->{'app'} eq $a->{'app'} } @n;
}
}
push @{$appointments}, @n;
}
elsif ($chosen_app && $data->{'view'} eq 'centre_view') {
#centre_view
$results = &subs::db_query("select max(timestamp) as timestamp,file,server_time,app,duration,type,status,amount,unit,project,account from appointments where app is not null and app=? and $timestamp_selector <=? order by $timestamp_selector DESC", $chosen_app,$time_definition);
$appointments = $results->hashes;
$results = &subs::db_query("select min(timestamp) as timestamp,file,server_time,app,duration,type,status,amount,unit,project,account from appointments where app is not null and app=? and $timestamp_selector >=? order by $timestamp_selector", $chosen_app,$time_definition);
push @{$appointments}, @{$results->hashes};
@{$appointments} = grep { $_->{'app'} eq $chosen_app } @{$appointments};
if (scalar @{$appointments} == 0) {
push @{$appointments}, { app => $chosen_app };
}
}
elsif ($chosen_app && $data->{'view'} eq 'appointment_details') {
#appointment_details;
my $t = &{$subs::time_subs->{$scope}}($timestamp); #timestamp at beginning
my $t1 = ($timestamp - $t);
my $t2 = ($t1 + $timestamp);
if ($data->{'uuid'}) {
$results = &subs::db_query("select * from appointments where app=? and uuid=? order by server_time DESC", $chosen_app, $data->{'uuid'});
}
elsif ($data->{'filter'} ne 'all') {
$results = &subs::db_query("select * from appointments where app=? and type=? and (($timestamp_selector >= ? AND $timestamp_selector <= ?) or ($timestamp_selector <= ? and (type=? or type=?))) order by timestamp DESC", $chosen_app, $data->{'filter'}, $t,$t2,$t2,'start','record');
}
else {
$results = &subs::db_query("select * from appointments where app=? and (($timestamp_selector >= ? AND $timestamp_selector <= ?) or ($timestamp_selector <= ? and (type=? or type=?))) order by timestamp DESC", $chosen_app,$t,$t2,$t2,'start','record');
}
$appointments = $results->hashes;
}
elsif ($chosen_app && $data->{'view'} eq 'appointment_display') {
# appointment_display (configure)
$results = &subs::db_query("select * from appointments where app=? order by $timestamp_selector limit 1", $chosen_app,$timestamp_selector);
$appointments = $results->hashes;
if (scalar @{$appointments} == 0) {
push @{$appointments}, { app => $chosen_app };
}
}
else {
# Just give it all to me.
# $results = &subs::db_query("select distinct(app) as app,* from appointments order by $timestamp_selector");
# $appointments = $results->hashes;
return 0;
}
$appts->{'__specs'}->{'stats'}->{'appts'}->{'first'} = $appointments->[0]->{'server_time'};
$appts->{'__specs'}->{'stats'}->{'appts'}->{'last'} = $appointments->[-1]->{'server_time'};
my $db_settings = &subs::db_select('settings', undef, { setting => 'pos' });
my $settings = $db_settings->hashes;
foreach my $s (@{$settings}) {
if ($s->{'setting'} eq 'pos' && $s->{'value'} eq 'account') {
push @{$appts->{'__accounts'}}, { formatted_name => &subs::format_name($s->{'app'}), app => $s->{'app'}} unless grep { $_->{'app'} eq $s->{'app'} } @{$appts->{'__accounts'}};
}
if ($s->{'setting'} eq 'pos' && $s->{'value'} eq 'project') {
push @{$appts->{'__projects'}}, { formatted_name => &subs::format_name($s->{'app'}), app => $s->{'app'}} unless grep { $_->{'app'} eq $s->{'app'} } @{$appts->{'__projects'}};
}
if ($s->{'setting'} eq 'pos' && $s->{'value'} eq 'account') {
push @{$appts->{'__accounts'}}, { formatted_name => &subs::format_name($s->{'app'}), app => $s->{'app'}} unless grep { $_->{'app'} eq $s->{'app'} } @{$appts->{'__accounts'}};
}
}
my @app_names = ( $device );
my $s_query = 'select * from settings where device = ? and (';
foreach my $a ( @{$appointments} ) {
unless ( grep { $_ eq $a->{'app'} } @app_names ) {
push @app_names, $a->{'app'};
$s_query .= ' or' if scalar @app_names > 2;
$s_query .= ' app = ?';
}
}
$s_query .= ')';
if (scalar @app_names > 1) {
$db_settings = &subs::db_query($s_query, @app_names);
my @app_settings = @{$db_settings->hashes};
if ($data->{'view'} eq 'appointment_viewer') {
if (my @invisible = grep { $_->{'setting'} eq 'visible' && $_->{'value'} ne 'checked' } @app_settings) {
foreach my $invisible ( @invisible ) {
@{$appointments} = grep { $_->{'app'} ne $invisible->{'app'} } @{$appointments};
@app_settings = grep { $_->{'app'} ne $invisible->{'app'} } @app_settings;
}
}
}
push @{$settings}, @app_settings;
}
$appts->{'__specs'}->{'stats'}->{'settings'}->{'first'} = $settings->[0]->{'server_time'};
$appts->{'__specs'}->{'stats'}->{'settings'}->{'last'} = $settings->[-1]->{'server_time'};
if ($stats) {
my $updateable = 0;
foreach my $table ( qw/appts settings/ ) {
if (scalar @{$appointments} != $stats->{'appts'}->{'count'} || $appts->{'__specs'}->{'stats'}->{$table}->{'last'} > $stats->{$table}->{'last'} || $appts->{'__specs'}->{'stats'}->{$table}->{'first'} < $stats->{$table}->{'first'}) {
$updateable = 1;
}
}
if ($updateable == 0) {
return { updateable => 'no', '__specs' => $appts->{'__specs'} };
}
$appts->{'__specs'}->{'stats'}->{'appts'}->{'count'} = scalar @{$appointments};
}
foreach my $a (@{$appointments}) {
next unless $a->{'app'};
# $a->{'file'} = undef if $data->{'view'} eq 'appointment_viewer';
my $cache_check;# = &subs::cache_get({ app => $a->{'app'}, context => $data->{'view'} });
if ($cache_check) {
$appts->{$a->{'app'}} = $cache_check;
# next;
}
$a->{'app'} = &subs::unformat_name($a->{'app'});
my @a_settings = grep { $_->{'app'} eq $a->{'app'} } @{$settings};
foreach my $s (grep { $_->{'app'} eq $a->{'app'} } @{$settings}) {
$appts->{$a->{'app'}}->{'setting'}->{$s->{'setting'}} = $s->{'value'};
foreach my $oi ( ($scope) ) {
if ($s->{'setting'} =~ /warranty|duration/gi) {
$appts->{$a->{'app'}}->{'setting'}->{$oi . '_' . $s->{'setting'}} = &subs::time_abbrev_translator($s->{'value'});
if (($a->{'type'} eq 'start' || $a->{'type'} eq 'record') && $a->{'timestamp'} < $timestamp) {# && (!$a->{'duration'} || ($a->{'duration'} >= $a->{'timestamp'} - $timestamp))) {
$a->{'duration'} = $a->{'timestamp'} - $timestamp;
}
unless ($a->{'type'} =~ /record|start/) {
if (my $dur = $a->{'duration'} || $appts->{$a->{'app'}}->{'setting'}->{$oi . '_' . $s->{'setting'}}) {
$a->{'formatted_' . $s->{'setting'}} = &subs::duration_sayer(($dur / 1000));
}
}
}
}
}
foreach my $at ( qw/model option option_category/ ) {
$appts->{$a->{'app'}}->{$at} = &subs::db_select($at, undef, { app=> $a->{'app'} })->hashes;
}
if ($data->{'view'} eq 'centre_view') {
my @bm = sort keys %{$gb::budget_modes};
$appts->{$a->{'app'}}->{'setting'}->{'budget_modes'} = \@bm;
foreach my $br ( @bm ) {
if (my $cache = &subs::cache_get({ app => $a->{'app'}, context => 'budget', subcontext => $br })) {
$appts->{$a->{'app'}}->{'budget'}->{$br} = $cache;
}
}
}
if ($a->{'duration'} !~ /[0-9]/) { $a->{'duration'} = 0; }
$appts->{$a->{'app'}}->{'timestamp'} = $a->{'timestamp'};
$appts->{$a->{'app'}}->{'name'} = &subs::unformat_name($a->{'app'});
$appts->{$a->{'app'}}->{'html_name'} = &subs::html_name($a->{'app'});
$appts->{$a->{'app'}}->{'http_name'} = &subs::http_name($a->{'app'});
$appts->{$a->{'app'}}->{'apostrophe_escape'} = &subs::apostrophe_escape($a->{'app'});
$appts->{$a->{'app'}}->{'setting'}->{'wiki'} = 'https://en.wikipedia.org/wiki/' . &subs::wiki_name($a->{'app'});
unless ($data->{'notes'} && $data->{'notes'} eq 'on') {
$a->{'start_notes'} = 'redacted' if $a->{'start_notes'};
$a->{'notes'} = 'redacted' if $a->{'notes'};
$a->{'end_notes'} = 'redacted' if $a->{'end_notes'};
}
$appts->{$a->{'app'}}->{'formatted_name'} = &subs::format_name($a->{'app'});
$appts->{$a->{'app'}}->{'shorthand_name'} = &subs::shorthand_name($appts->{$a->{'app'}}->{'formatted_name'});
$a->{'formatted_time'} = localtime($a->{'timestamp'} / 1000 )->strftime('%a %b %d %Y - %I:%M:%S%P');
$a->{'formatted_server_time'} = localtime($a->{'server_time'} / 1000 )->strftime('%a %b %d %Y - %I:%M:%S%P %Z');
$appts->{$a->{'app'}}->{'just_time'} = localtime($a->{'timestamp'} / 1000 )->strftime('%I:%M%P');
$appts->{$a->{'app'}}->{'just_date'} = localtime($a->{'timestamp'} / 1000 )->strftime('%a %b %d %Y');
if (!$a->{'duration'} && grep { 'duration' eq $_->{'setting'} } @a_settings ) {
$a->{'duration'} = &subs::time_abbrev_translator($appts->{$a->{'app'}}->{'setting'}->{'duration'});
}
if ($a->{'timestamp'} < $timestamp && ($a->{'type'} eq 'start' || $a->{'type'} eq 'record')) {
$a->{'duration'} = $a->{'timestamp'} - $timestamp;
}
$appts->{$a->{'app'}}->{'duration'} = $a->{'duration'};
$a->{'formatted_duration'} = &subs::duration_sayer(abs $a->{'duration'} / 1000);
$a->{'warranty'} = $a->{'warranty'} || $appts->{$a->{'app'}}->{'setting'}->{'warranty'};
$appts->{$a->{'app'}}->{'formatted_duration'} = &subs::duration_sayer($a->{'duration'});
$appts->{$a->{'app'}}->{'formatted_duration'} = &subs::duration_sayer((time() - $a->{'timestamp'})) unless $a->{'duration'};
$appts->{$a->{'app'}}->{'file'} = $a->{'file'};
if ($a->{'file'} ) {
if ($a->{'type'} eq 'snapshot') {
push @{$a->{'files'}}, { file => $a->{'file'}, file_type => 'img' };
}
else {
my $files = eval { return decode_json $a->{'file'} } || [];
if (eval { $files->{'f'} }) {
$files = [ $files ];
}
foreach my $file (@{$files}) {
my $f = $file->{'f'};
# my ($destination,$asset) = &subs::file_device_renamer($f,$a->{'app'},$misc_settings);
# if ($f ne $destination . $asset) {
# $f = $destination . $asset;
# }
my $tf = {
file => $f,
uuid => $file->{'uuid'},
server_time => $file->{'server_time'},
function => $file->{'function'},
type => $file->{'type'},
name => $file->{'name'},
app => $a->{'app'}
};
$tf->{'file_type'} = 'img' if $f =~ /jpg|png|bmp|tiff|xcf/;
$tf->{'file_type'} = 'snd' if $f =~ /wav|mp3|aiff|weba|m4a|flac/;
$tf->{'file_type'} = 'vid' if $f =~ /mp4|avi|mov|webm|mkv/;
$tf->{'file_type'} = 'pdf' if $f =~ /pdf/;
$tf->{'file_type'} = 'doc' if $f =~ /doc|docx|xls|xlsx|pub|pubx|txt|rtf/;
push @{$a->{'files'}}, $tf;
}
}
}
@appointments = grep { $_ ne $a->{'app'} } @appointments;
unshift @appointments, $a->{'app'};
if ($appts->{$a->{'app'}}->{'total'} || $appts->{$a->{'app'}}->{'amount'}) {
$a->{'label'} = "transaction";
$a->{'type'} = "transaction";
$appts->{$a->{'app'}}->{'total_amount'} += unformat_number($a->{'amount'});
$appts->{$a->{'app'}}->{'total_tax'} += unformat_number($a->{'tax'});
$appts->{$a->{'app'}}->{'total_total'} += unformat_number($a->{'total'});
$appts->{$a->{'app'}}->{'total_quantity'} += unformat_number($a->{'quantity'});
$appts->{$a->{'app'}}->{'formatted_time'} = localtime($a->{'timestamp'} / 1000 )->strftime('%a %b %d %Y - %I:%M:%S%P');
push @{$appts->{$a->{'app'}}->{'vendors'}}, $a->{'vendor'};
$appts->{$a->{'app'}}->{'last_transaction'} = $appts->{$a->{'app'}}->{'timestamp'};
$appts->{$a->{'app'}}->{'vendor_list'} = encode_json $appts->{$a->{'app'}}->{'vendors'};
}
if ($a->{'amount'}) {
$appts->{$a->{'app'}}->{'total_amount'} -= $a->{'amount'} if $a->{'amount'} < 0;
}
my $timestamp = $a->{'timestamp'};
my $type = $a->{'type'};
$a->{'formatted_name'} = &subs::format_name($a->{'app'});
push @{$appts->{$a->{'app'}}->{'list'}}, $a;
$appts->{$a->{'app'}}->{'last_event'} = $timestamp;
$a->{'formatted_account'} = &subs::format_name($a->{'account'});
$a->{'formatted_type'} = &subs::format_name($a->{'type'});
$a->{'formatted_project'} = &subs::format_name($a->{'project'});
if ($project && $project ne 'all') {
$appts->{$a->{'app'}}->{'last_project'} = $project;
}
else {
$appts->{$a->{'app'}}->{'last_project'} = $a->{'project'};
}
if ($account && $account ne 'all') {
$appts->{$a->{'app'}}->{'last_account'} = $account;
}
else {
$appts->{$a->{'app'}}->{'last_account'} = $a->{'account'};
}
# if ($type =~ 'start|record|pause|transaction|reset|note') {
$appts->{$a->{'app'}}->{'last_reset'} = $timestamp;
# }
if ($json->{'type'} && $json->{'type'} eq 'inventory') {
$appts->{$a->{'app'}}->{'invs'} += $json->{'inv'};
$appts->{$a->{'app'}}->{'inv'} = $appts->{$a->{'app'}}->{'resets'} ;
}
$a->{'duration'} = '' if $a->{'duration'} eq 'NaN';
if ($a->{'type'} =~ /start|record/) {
$appts->{$a->{'app'}}->{'formatted_start_time'} = $a->{'formatted_time'};
$appts->{$a->{'app'}}->{'formatted_end_time'} = &subs::formatted_time($a->{'timestamp'} + ($a->{'duration'} || 0));
}
else {
$appts->{$a->{'app'}}->{'formatted_end_time'} = $a->{'formatted_time'};
$appts->{$a->{'app'}}->{'formatted_start_time'} = &subs::formatted_time($a->{'timestamp'} - ($a->{'duration'} || 0));
}
push @{$appts->{$a->{'app'}}->{'transactions'}}, grep { $_->{'type'} eq 'transaction' && $_->{'app'} eq $a->{'app'} } @{$appointments};
$appts->{$a->{'app'}}->{'setting'}->{'status'} = $appts->{$a->{'app'}}->{'list'}->[-1]->{'type'} unless $appts->{$a->{'app'}}->{'setting'}->{'status'} && $appts->{$a->{'app'}}->{'setting'}->{'status'} =~ /record|start|paused|resumed|completed|transaction/;
# &subs::cache_set({app => $a->{'app'}, context => $data->{'view'} }, $appts->{$a->{'app'}});
}
return $appts;
}
get '/manager/voice_prompt' => sub ($c) {
# Mojo::IOLoop->subprocess->run_p(sub {
if ($device eq 'mobile') {
my $text;
if ($c->param('repeater') eq 'yes') {
while ( lc $text ne 'cancel' && $text ne '' ) {
my $json = `termux-dialog speech`;
$json = eval { return decode_json $json } || {};
$text = $json->{'text'};
&Websocket::send('server', { console => 'said_it(\'' . $text . '\')' });
sleep 1;
}
}
else {
$text = `termux-speech-to-text`;
chomp($text);
&Websocket::send('server', { console => 'said_it(\'' . $text . '\')' });
}
}
#});
$c->render('text' => 'ok');
};
get '/download_program' => sub($c) {
unless ($c->session('downloading_program')) {
my $download_count = &subs::setting_grabber({ app => '__president', setting => 'download_count' }) || 0;
my $zipper = `zip -x ./server/* ./config.json ./public/images/jonathans -r - ./ | cat`;
my $timestamp = &subs::rightNow();
$c->render_file(data => $zipper, filename => 'president_' . $timestamp . '.zip');
$download_count = $download_count + 1;
&subs::setting_setter({ app => '__president', setting => 'download_count', value => $download_count });
$c->session('downloading_program', 'no');
}
};
post '/manager/cache_set' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $context = $c->param('context');
my $subcontext = $c->param('subcontext');
my $data = eval { return decode_json $c->param('data') } || {};
&subs::cache_set({ app => $app, context => $context, subcontext => $subcontext, timestamp => $timestamp }, $data);
$c->render('text' => 'ok');
};
post '/manager/cache_delete' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $context = $c->param('context');
my $subcontext = $c->param('subcontext');
&subs::cache_delete({ app => $app, context => $context, subcontext => $subcontext });
$c->render('text' => 'deleted');
};
get '/manager/cache_get' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $context = $c->param('context');
my $subcontext = $c->param('subcontext');
my $cache = &subs::cache_get({ app => $app, context => $context, subcontext => $subcontext });
$c->render(json => $cache);
};
get '/manager/download_file' => sub ($c) {
my $file = $c->param('file');
my $app = uri_decode( $c->param('app') );
my $uuid = $c->param('uuid');
my $timestamp = $c->param('timestamp');
my $server_time = $c->param('server_time');
my ($db,$database,$sql) = &subs::database_grabber();
my $appt = &subs::db_query('select * from appointments where app = ? and uuid = ?', $app, $uuid)->hashes->[0];
my $encryption_standard = $appt->{'encryption_standard'};
my $saved_file = eval { return decode_json $appt->{'file'} } || [{}];
@{$saved_file} = grep { $_->{'f'} eq $file } @{$saved_file};
my ($data,$filename);
if (-e $file) {
if ($file =~ /\.enc$/gi) {
my $suds = $c->session('suds');
my $passwords = &subs::db_query('select * from security where level != ? order by server_time DESC', 'padlock');
my $pwords = $passwords->hashes;
foreach my $p ( @{$pwords} ) {
my $secret = &subs::decrypter($suds, $p->{'credential'});
my $process_data = `openssl enc -d -k "$secret" -$encryption_standard -pbkdf2 -in $file`;
my $ft = File::Type->new();
my $type_from_data = $ft->checktype_contents($process_data);
if ($type_from_data ne 'application/octet-stream' || ($data =~ /webm/)) {
$data = $process_data;
my @file = split '/', $file;
$filename = $file[-1];
$filename =~ s/\.enc//gi;
$filename = $saved_file->[0]->{'of'} if $saved_file->[0]->{'of'};
last;
}
}
}
else {
$data = read_file($file);
my @file = split '/', $file;
$filename = $file[-1];
$filename = $saved_file->[0]->{'of'} if $saved_file->[0]->{'of'};
}
$c->render_file(data => $data, filename => $filename);
}
else {
$c->render(text => 'Not Found');
}
};
post '/manager/upload_file' => sub ($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my @uploads = @{$c->req->uploads};
my $timestamp = $c->param('timestamp') - 1;
my $duration = $c->param('duration');
my $app = $c->param('app');
my $uuid = $c->param('uuid') || &subs::random_string_creator(22);
my $seen_appts = [];
my $notes;
my @uploaded_files;
my @uuids;
if ($c->param('uuid')) {
$seen_appts = &subs::db_select('appointments', undef, { uuid => $uuid })->hashes;
if (scalar @{$seen_appts} > 0) {
my $appt = $seen_appts->[0];
my $of = eval { return decode_json $appt->{'file'} } || [];
push @uploaded_files, @{$of};
$app = $appt->{'app'};
$notes = &subs::note_decrypter($c->session('suds'), $appt->{'notes'},$appt->{'server_time'}) . '
';
}
}
my $returner = { uuid => $uuid, app => $app, timestamp => $timestamp };
my $upload_type;
my $linux_file;
my $resolution = &subs::setting_grabber({ app => 'misc', setting => 'photo_size' } ) || '1920x1080';
foreach my $u ( @uploads ) {
my $is_enc = 0;
my $server_time = &subs::rightNow();
$timestamp++;
my $filen = &subs::unformat_name($u->filename);
my @f = split /\./, $filen;
if (lc $f[-1] eq 'enc') {
$is_enc = 1;
pop @f;
}
my $ext = pop @f;
$filen = join '.', @f;
my $fn = $filen . '_' . $timestamp . '.' . $ext;
my $upload = {
type => $u->headers->content_type,
path => $u->asset->path,
filename => $fn,
size => $u->size,
};
$app = $upload->{'filename'} unless $c->param('app');
$app = &subs::unformat_name($app);
my $init = &subs::setting_initializer($app,$timestamp);
$app = $init->{'app'};
my ($folder,$location,$thumb);
if ($upload->{'type'} =~ /audio/gi) {
$upload_type = 'audio';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'rec_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /video/gi || lc $ext eq 'webm' || lc $ext eq 'avi' || lc $ext eq 'mp4' || lc $ext eq 'mov' || lc $ext eq 'mkv') {
$upload_type = 'video';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'video_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
$thumb = $location . '/thumbs';
}
elsif ($upload->{'type'} =~ /image/gi || lc $ext eq 'jpg' || lc $ext eq 'png') {
$upload_type = 'image';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'photo_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
$thumb = $location . '/thumbs';
}
elsif ($upload->{'type'} =~ /pdf/gi) {
$upload_type = 'scan';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'document_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
elsif ($upload->{'type'} =~ /application/gi) {
$upload_type = 'software';
$folder = &subs::setting_grabber( { app => 'misc', setting => 'download_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
else {
$folder = &subs::setting_grabber( { app => 'misc', setting => 'download_location', device => $device } );
$location = &subs::home($folder) . '/' . $app;
}
`mkdir -p $location` unless -e $location;
my $filename = $location . '/' . $upload->{'filename'};
my $new_uuid = &subs::random_string_creator(13);
if ($is_enc == 1) {
$filename = $filename . '.enc';
push @uuids, $new_uuid;
}
$u->move_to($filename);
my $ocr;
if ($upload_type eq 'image') {
`magick $filename -resize $resolution $filename` unless lc $resolution eq 'raw';
$ocr = &ocr_reader($c,$filename);
}
$linux_file .= `file $filename` . "\n";
if ($upload->{'filename'} =~ /avi$|mkv$/gi) {
my $old_filename = $filename;
$filename =~ s/avi$|mkv$/mp4/;
my $tn_o = &subs::terminal_name($old_filename);
my $tn_f = &subs::terminal_name($filename);
threads->create(sub() {
`ffmpeg -i $tn_o $tn_f & exit /b`;
`shred -u $tn_o`;
&subs::file_encrypter({ app => $app });
});
}
my $u_data = { server_time => &subs::rightNow(), ocr => $ocr, f => $filename, uuid => $new_uuid, type => $upload_type };
if ($thumb) {
`mkdir -p $thumb` unless -e $thumb;
$u_data->{'thumb'} = $thumb . '/' . $upload->{'filename'};
$u_data = &thumbnail_creator($u_data);
}
push @uploaded_files, $u_data;
}
my $jfile = encode_json \@uploaded_files;
if (@{$seen_appts} > 0) {
&subs::db_update('appointments', {
timestamp => $timestamp,
notes => &subs::note_encrypter($c->session('suds'),$notes . $linux_file),
file => $jfile,
uuid => $uuid,
duration => $duration || '1000',
encryption_standard => undef,
},
{
uuid => $uuid,
app => $app
});
&Websocket::send($app, { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');' });
}
else {
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
notes => &subs::note_encrypter($c->session('suds'),$notes . $linux_file),
type => $upload_type || $c->param('type') || 'upload',
file => $jfile,
uuid => $uuid,
duration => $duration || '1000',
browser_tab_id => $c->param('browser_tab_id')
};
&appointment_writer($c,$write);
}
&subs::file_encrypter({ app => &subs::unformat_name($app) });
$returner->{'cv'} = ¢re_view_grabber({ c => $c, app => &subs::unformat_name($app), timestamp => $timestamp });
$c->render(json => $returner);
};
sub thumbnail_creator($data) {
if ($data->{'thumb'}) {
$data = &subs::file_media_information($data,$data->{'f'});
my $thumbnail_size = &subs::setting_grabber({ app => 'misc', setting => 'thumbnail_size' }) || 'none';
if ($thumbnail_size ne 'none') {
my $filename = $data->{'f'};
my $upload_type = $data->{'type'};
my $thumb = $data->{'thumb'};
my @filename = split /\./, $filename;
my $ext = $filename[-1];
my @thumb = split /\./, $thumb;
pop @thumb;
push @thumb, 'png';
$thumb = join '.', @thumb;
$data->{'thumb'} = $thumb;
if ($upload_type eq 'video') {
my $command2 = 'ffmpeg -ss 00:00:00.010 -i ' . $filename . ' -vframes 1 -c:v png -f image2pipe - | magick - -resize ' . $thumbnail_size . ' ' . $thumb;
`$command2`;
}
elsif ($upload_type eq 'image' || $upload_type eq 'document') {
my $command2 = 'magick ' . $filename . ' -resize ' . $thumbnail_size . ' ' . $thumb;
`$command2`;
}
else {
return $data;
}
}
}
if ($data->{'app_uuid'} && $data->{'file_uuid'}) {
my $appt = &subs::db_query('select * from appointments where uuid = ? and file is not null', $data->{'app_uuid'} )->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
if (scalar @{$files} > 0) {
my $written = 0;
foreach my $f ( @{$files} ) {
if ($f->{'uuid'} eq $data->{'file_uuid'}) {
$f->{'thumb'} = $data->{'thumb'};
$f->{'server_time'} = &subs::rightNow();
$written = 1;
}
}
if ($written == 1) {
my $jfile = encode_json $files;
&subs::db_update('appointments', { file => $jfile, server_time => &subs::rightNow() }, { uuid => $appt->{'uuid'}, app => $appt->{'app'} });
}
}
}
delete $data->{'app_uuid'};
delete $data->{'file_uuid'};
return $data;
}
post '/manager/configure/image_function' => sub($c) {
my $app = $c->param('app');
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
my $function = $c->param('func');
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my $backgrounds = eval { return decode_json &subs::setting_grabber({ app => 'marker', setting => 'backgrounds' }) } || [];
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'embedded', setting => 'diagrams' }) } || [];
my $receipts = eval { return decode_json &subs::setting_grabber({ app => 'budget', setting => 'receipts' }) } || [];
my $signatorials = eval { return decode_json &subs::setting_grabber({ app => 'customs', setting => 'signatorials' }) } || [];
unless ($function eq 'map') {
@{$maps} = grep { $_->{'uuid'} ne $file_uuid } @{$maps};
}
unless ($function eq 'background') {
@{$backgrounds} = grep { $_->{'uuid'} ne $file_uuid } @{$backgrounds};
}
unless ($function eq 'diagram') {
@{$diagrams} = grep { $_->{'uuid'} ne $file_uuid } @{$diagrams};
}
unless ($function eq 'receipt') {
@{$receipts} = grep { $_->{'uuid'} ne $file_uuid } @{$receipts};
}
unless ($function eq 'signatorial') {
@{$signatorials} = grep { $_->{'uuid'} ne $file_uuid } @{$signatorials};
}
foreach my $fi ( @{$files} ) {
if ( $fi->{'uuid'} eq $file_uuid) {
$fi->{'function'} = $function;
$fi->{'app'} = $app;
$fi->{'app_uuid'} = $appt->{'uuid'};
if ($function eq 'map') {
push @{$maps}, $fi;
}
elsif ($function eq 'background') {
push @{$backgrounds}, $fi;
}
elsif ($function eq 'diagram') {
push @{$diagrams}, $fi;
}
elsif ($function eq 'receipt') {
push @{$receipts}, $fi;
}
elsif ($function eq 'signatorial') {
push @{$signatorials}, $fi;
}
}
}
my $jmaps = encode_json $maps;
my $jbacks = encode_json $backgrounds;
my $jdiagrams = encode_json $diagrams;
my $jreceipts = encode_json $receipts;
my $jsignatorials = encode_json $signatorials;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
&subs::setting_setter({ app => 'marker', setting => 'backgrounds', value => $jbacks });
&subs::setting_setter({ app => 'embedded', setting => 'diagrams', value => $jdiagrams });
&subs::setting_setter({ app => 'budget', setting => 'receipts', value => $jreceipts });
&subs::setting_setter({ app => 'customs', setting => 'signatorials', value => $jsignatorials });
my $jfile = encode_json $files;
$appt->{'file'} = $jfile;
$appt->{'server_time'} = &subs::rightNow();
&subs::db_update('appointments', $appt, { uuid => $appt->{'uuid'}, app => $appt->{'app'} });
$c->render(json => $appt);
&image_function_sanity_check();
};
post '/manager/configure/image_function_tool' => sub($c) {
my $app_uuid = $c->param('app_uuid');
my $app = $c->param('app');
my $file_uuid = $c->param('file_uuid');
my $tool = $c->param('tool');
my $value = $c->param('value');
my $translate = $c->param('translate');
$value = eval { return decode_json $value } || {};
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
my $home_plate = eval { return decode_json &subs::setting_grabber({ app => $value->{'legend'}, setting => 'home_plate' }) } || {};
if ($tool eq 'home_plate') {
foreach my $hp ( keys %{$home_plate} ) {
$value->{$hp} = $home_plate->{$hp};
}
}
elsif ($tool eq 'scale') {
if ($value->{'legend'} =~ /[a-zA-z]/gi) {
my ($fo,$ev,$uom,$format) = &formula_calculator($value->{'legend'} . ' to m' );
$value->{'legend'} = $ev;
}
}
foreach my $fi ( @{$files} ) {
$fi->{$tool} = $value if $fi->{'uuid'} eq $file_uuid;
}
foreach my $map ( @{$maps} ) {
$map->{$tool} = $value if $map->{'uuid'} eq $file_uuid;
}
$value->{'formatted_legend'} = &subs::format_name($value->{'legend'});
my $jmaps = encode_json $maps;
my $jfiles = encode_json $files;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
&subs::db_update('appointments', { server_time => &subs::rightNow(), file => $jfiles }, { app => $appt->{'app'}, uuid => $appt->{'uuid'} });
$c->render(json => $value);
};
sub image_function_sanity_check() {
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my $backgrounds = eval { return decode_json &subs::setting_grabber({ app => 'marker', setting => 'backgrounds' }) } || [];
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'handbook', setting => 'diagrams' }) } || [];
foreach my $map ( @{$maps} ) {
unless ( -e $map->{'f'} ) {
@{$maps} = grep { $_->{'uuid'} ne $map->{'uuid'} } @{$maps};
}
}
foreach my $background ( @{$backgrounds} ) {
unless ( -e $background->{'f'} ) {
@{$backgrounds} = grep { $_->{'uuid'} ne $background->{'uuid'} } @{$backgrounds};
}
}
foreach my $diagram ( @{$diagrams} ) {
unless ( -e $diagram->{'f'} ) {
@{$diagrams} = grep { $_->{'uuid'} ne $diagram->{'uuid'} } @{$diagrams};
}
}
my $jmaps = encode_json $maps;
my $jbacks = encode_json $backgrounds;
my $jdiagrams = encode_json $diagrams;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
&subs::setting_setter({ app => 'marker', setting => 'backgrounds', value => $jbacks });
&subs::setting_setter({ app => 'handbook', setting => 'diagrams', value => $jdiagrams });
}
post '/manager/configure/image_name' => sub($c) {
my $name = &subs::unformat_name($c->param('name'));
my $app_uuid = $c->param('app_uuid');
my $file_uuid = $c->param('file_uuid');
my $app = $c->param('app');
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
foreach my $file ( @{$files} ) {
if ( $file->{'uuid'} eq $file_uuid) {
$file->{'name'} = $name;
}
}
my $jfiles = encode_json $files;
&subs::db_update('appointments', { server_time => &subs::rightNow(), file => $jfiles }, { app => $app, uuid => $app_uuid });
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my $backgrounds = eval { return decode_json &subs::setting_grabber({ app => 'marker', setting => 'backgrounds' }) } || [];
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'handbook', setting => 'diagrams' }) } || [];
foreach my $map ( @{$maps} ) {
if ( $map->{'uuid'} eq $file_uuid ) {
$map->{'name'} = $name;
}
}
foreach my $background ( @{$backgrounds} ) {
if ($background->{'uuid'} eq $file_uuid ) {
$background->{'name'} = $name;
}
}
foreach my $diagram ( @{$diagrams} ) {
if ($diagram->{'uuid'} eq $file_uuid) {
$diagram->{'name'} = $name;
}
}
my $jmaps = encode_json $maps;
my $jbacks = encode_json $backgrounds;
my $jdiagrams = encode_json $diagrams;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
&subs::setting_setter({ app => 'marker', setting => 'backgrounds', value => $jbacks });
&subs::setting_setter({ app => 'handbook', setting => 'diagrams', value => $jdiagrams });
$c->render(json => $appt);
};
post '/manager/travel/delete_map' => sub($c) {
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
my $app = $c->param('app');
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
foreach my $file ( @{$files} ) {
if ($file->{'uuid'} eq $file_uuid) {
delete $file->{'function'};
delete $file->{'scale'};
delete $file->{'home_plate'};
}
}
@{$maps} = grep { $_->{'uuid'} ne $file_uuid } @{$maps};
my $jfiles = encode_json $files;
my $jmaps = encode_json $maps;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
&subs::db_update('appointments', { file => $jfiles, server_time => &subs::rightNow() }, { uuid => $appt->{'uuid'}, app => $app });
$c->render(json => $maps);
};
post '/manager/continent/record' => sub ($c) {
my $returner = &continent_record($c);
$c->render(json => $returner);
};
sub continent_record($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $app = &subs::unformat_name($c->param('app'));
my $device = $c->param('device') || &subs::device_setter();
my $server_time = &subs::rightNow();
my $timestamp = $c->param('timestamp');
my $warranty = $c->param('warranty') || &subs::ago_calc(&subs::setting_grabber({ app => 'app', setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' }),$server_time);
my $navigation = $c->param('navigation');
my $returner = {};
my $purpose = $c->param('purpose');
my $scope = $c->param('scope');
my ($uuid,$pre_uuid);
if ($c->param('uuid')) {
$pre_uuid = $c->param('uuid');
$uuid = $c->param('uuid') . '-' . &subs::random_string_creator(8);
}
else {
$uuid = &subs::random_string_creator(25);
$pre_uuid = $uuid;
}
if ($navigation ne 'once') {
my $continentals = &subs::db_query('select * from continent where app = ? and uuid = ? order by server_time DESC LIMIT 1', $app, $uuid)->hashes;
if ($continentals->[0]->{'latitude'} eq $c->param('latitude') && $continentals->[0]->{'longitude'} eq $c->param('longitude')) {
$returner = $continentals->[0];
return $returner;
}
}
if (my $alt = $c->param('latitude')) {
$returner = {
timestamp => $timestamp,
latitude => $c->param('latitude'),
longitude => $c->param('longitude'),
accuracy => sprintf("%.2F", $c->param('accuracy')),
server_time => $server_time,
uuid => $uuid,
type => $purpose,
app => $app,
warranty => $warranty,
};
&subs::db_insert('continent', $returner);
if ($purpose eq 'proxy_load' && $scope) {
&Websocket::send('server', { console => 'listProxy(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'proxy_set' && $scope) {
&Websocket::send('server', { console => 'setProxy(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'travel_viewer' && $scope) {
&Websocket::send('server', { console => 'travelViewer(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'home_plate') {
my $json = encode_json $returner;
&subs::setting_setter({ app => 'me', device => $device, setting => 'home_plate', value => $json });
}
&Websocket::send($app, { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $pre_uuid .'\');' });
}
if ($returner->{'navigation'} ne 'once') {
$returner->{'navigation'} = &subs::ago_calc('-' . ($navigation || 60000), $server_time);
}
return $returner;
}
post '/manager/continent/record_anyway' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $app = &subs::unformat_name($c->param('app'));
my $timestamp = $c->param('timestamp');
my $server_time = &subs::rightNow();
my $watch = &subs::device_lister($timestamp,'teletype') || {};
Mojo::IOLoop->subprocess->run_p(sub {
my ($uuid,$pre_uuid);
if ($c->param('uuid')) {
$pre_uuid = $c->param('uuid');
$uuid = $c->param('uuid') . '-' . &subs::random_string_creator(8);
}
else {
$uuid = &subs::random_string_creator(25);
$pre_uuid = $uuid;
}
my $warranty => $c->param('warranty') || &subs::ago_calc(&subs::setting_grabber({ app => $app, setting => 'warranty' }) || &subs::setting_grabber({ app => 'me', setting => 'warranty' }),$server_time);
my $purpose = $c->param('purpose') || 'home_plate';
my $returner = {
timestamp => $timestamp,
server_time => $server_time,
uuid => $uuid,
type => $purpose,
app => $app,
warranty => $warranty
};
my $scope = $c->param('scope');
if ($watch->{'ip'}) {
my $ping = 'timeout .2 ping -c 1 ' . $watch->{'ip'};
my $ping_test = `$ping`;
if ($ping_test =~ /ttl/gi) {
my $ua = Mojo::UserAgent->new();
$ua->connect_timeout(1);
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/my_position';
my $res = eval { return $ua->insecure(1)->get($watch_home)->result };
if (eval { return decode_json $res->body }) {
my $co = eval { return decode_json $res->body };
$returner->{'latitude'} = $co->{'lat'};
$returner->{'longitude'} = $co->{'lng'};
}
}
}
unless ($returner->{'latitude'}) {
if ($purpose ne 'app') {
my $home_plate = &subs::setting_grabber({ 'app' => 'me', setting => 'home_plate' });
if (my $hp = eval { return decode_json $home_plate }) {
foreach my $k ( keys %{$hp} ) {
next if grep { $k eq $_ } qw/altitude speed pathname hostname user_agent protocol/;
$returner->{$k} = $hp->{$k} unless $returner->{$k};
}
&subs::db_insert('continent', $returner);
}
}
}
else {
&subs::db_insert('continent', $returner);
}
if ($purpose eq 'proxy_load' && $scope) {
&Websocket::send('server', { console => 'listProxy(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'proxy_set' && $scope) {
&Websocket::send('server', { console => 'setProxy(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'travel_viewer' && $scope) {
&Websocket::send('server', { console => 'travelViewer(' . $timestamp . ',"' . $uuid . '");' });
}
elsif ($purpose eq 'home_plate') {
my $json = encode_json $returner;
&subs::setting_setter({ app => 'me', setting => 'home_plate', value => $json });
}
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $pre_uuid .'\');' });
});
$c->render('text' => 'ok');
};
post '/manager/continent/delete' => sub($c) {
my $uuid = $c->param('uuid');
my $server_time = $c->param('server_time');
&subs::db_delete('continent', { uuid => $uuid });
&deletion_registration({ table => 'continent', uuid => $uuid, server_time => $server_time });
$c->render(json => { uuid => $uuid });
};
sub schedule_maker($c,$schedule,$timestamp) {
my $app = $c->param('app');
my $warranty ='';
my $original_timestamp = $c->param('timestamp');
$timestamp = $c->param('timestamp');
my @returner;
if ($schedule eq 'once') {
push @returner, $schedule;
}
else {
if ($schedule =~ /for/gi) {
my @schedule = split ' for ', $schedule;
$warranty = $schedule[1];
$schedule = $schedule[0];
}
my $renamed_schedule = $schedule;
$renamed_schedule =~ s/ly$//gi;
my $rsnumber = $renamed_schedule;
my $rsword = $renamed_schedule;
$rsnumber =~ s/[^0-9,.]//gi;
$rsword =~ s/[^[a-zA-Z]//gi;
$rsword = &subs::timespan_widener($rsword);
if (eval {&{$subs::time_subs->{$rsword}}() }) {
my $t = &{$subs::time_subs->{$rsword}}($timestamp,$rsnumber);
my $diff = $timestamp - $t;
my $settings = &subs::settings_grabber({ app => $c->param('app') });
$warranty = $settings->{'warranty'} unless $warranty ne '';
$warranty = &subs::ago_calc($warranty,$c->param('timestamp'));
my $locking_status = $c->param('lockingStatus');
my $usual_duration = $settings->{'duration'};
if ($locking_status eq 'on') {
$c->param('duration', $usual_duration)
}
my $duration = &subs::time_abbrev_translator($c->param('duration'));
$duration = &subs::time_abbrev_translator($usual_duration) unless $c->param('duration') =~ /[a-z0-9A-Z]/;
if ($c->param('type') eq 'start' || $c->param('type') eq 'record') {
$duration = $duration * -1;
}
my $count = 0;
until ($timestamp >= $warranty) {
if ($timestamp != $original_timestamp || $count != 0) {
$c->param('timestamp',$timestamp);
my $stop_timestamp = $c->param('duration') =~ /[a-zA-Z0-9]/ ? $timestamp - ((abs $duration) * -1) : undef;
push @returner, $timestamp;
&appointment_writer($c, {
app => $app,
timestamp => $timestamp,
type => $c->param('type'),
project => $settings->{'project'},
duration => $duration,
stop_timestamp => $stop_timestamp,
source_uuid => $c->param('uuid')
});
}
$timestamp = $timestamp + $diff;
$count++;
}
}
return \@returner;
}
}
sub remote_relay_request($c) {
unless ($c->param('remoted') eq 'yes') {
my $remote_uuid = $c->param('remote_uuid');
if (1 == 1) {
$c->param('subprocess' => undef);
# return &relay_the_request($c);
my $path = $c->req->url->path;
my $uuid = $c->param('uuid');
my $server_time = &subs::rightNow();
my $remote_machines;
if ($remote_uuid) {
$remote_machines = &subs::db_query('select * from remote_machines where connection=? and uuid=?', 'active', $remote_uuid)->hashes;
}
else {
$remote_machines = &subs::db_query('select * from remote_machines where connection=?', 'active')->hashes;
}
foreach my $rm ( @{$remote_machines} ) {
$rm = &remote_useragent_maker({ ip => $rm->{'ip'}, signatorial => $rm->{'signatorial'}, rm => $rm });
my $method = lc $c->req->method;
my $res;
if ($method eq 'post') {
my $params = $c->req->body_params->{'string'};
$params .= '&remoted=yes&server_time=' . $server_time . '&uuid=' . $uuid;
$params .= '&remote_uuid=' . $remote_uuid unless $path eq '/file_open' ;
my $url = $rm->{'manager'} . $path . '?' . $params;
$res = $rm->{'ua'}->post($url)->result;
return $res->body;
}
else {
my $all_params = $c->req->query_params;
my $params;
for (my $n = 0; $n < scalar @{$all_params->{'pairs'}} - 1; $n++) {
if ($all_params->{'pairs'}->[$n] eq 'file' || $all_params->{'pairs'}->[$n] eq 'track') {
$all_params->{'pairs'}->[$n + 1] = url_escape $all_params->{'pairs'}->[$n + 1];
}
$params .= '&' . $all_params->{'pairs'}->[$n] . '=' . $all_params->{'pairs'}->[$n + 1];
$n++;
}
$params .= '&remoted=yes&server_time=' . $server_time . '&uuid=' . $uuid;
$params .= '&remote_uuid=' . $remote_uuid;
my $url = $rm->{'manager'} . $path . '?' . $params;
$rm->{'ua'} = $rm->{'ua'}->max_response_size(0);
$res = $rm->{'ua'}->get($url);# => { Accept => '*/*' } => 'Content!');
if ($path eq '/file_open' || $path eq '/play') {
my $data = $res->res->content->asset->slurp;
return $data;
}
else {
return $res->result->body;
}
}
my $additions = eval { return decode_json $rm->{'additions'} } || [];
# push @{$additions}, { app => $app, uuid => $uuid, scope => 'single', initialization => &subs::rightNow() };
my $jadditions = encode_json $additions;
# &subs::db_update('remote_machines', { additions => $jadditions }, { uuid => $rm->{'uuid'}, signatorial => $rm->{'signatorial'} });
}
}
}
}
post '/manager/reset' => sub ($c) {
my $content = &manager_reset($c);
$c->render(json => $content );
};
sub manager_reset($c) {
if (($c->param('account') eq 'gallery' && &subs::setting_grabber({ app => 'me', setting => 'gallery_appts' }) eq 'off' )) {
return { 'cv' => 'inapplicable' };
}
my $timestamp = ×tamp_adjuster($c);
my $app = &subs::unformat_name($c->param('app'));
# &subs::cache_delete({ app => $app, context => 'template' });
my $browser_tab_id = $c->param('browser_tab_id');
my $locking_status = $c->param('lockingStatus');
my $server_time = $c->param('server_time') || &subs::rightNow() || $timestamp;
my $type = $c->param('type');
# ($app,undef,$type) = &subs::typesetter($app);
$type = $type || $c->param('type');
my $init = &subs::setting_initializer($app,$timestamp);
$app = $init->{'app'};
$c->param('app' => $app);
my $uuid = $c->param('uuid') || &subs::random_string_creator(40);
$c->param('uuid' => $uuid);
my $returner = { app => $app, timestamp => $timestamp, server_time => $server_time, init => $init, uuid => $uuid };
my $source = $c->param('source');
my $measure_is_open = $c->param('measure_is_open');
my $usual_duration = $init->{'duration'};
if ($locking_status eq 'on') {
$c->param('duration', $usual_duration)
}
my $duration = &subs::time_abbrev_translator($c->param('duration'));
$duration = &subs::time_abbrev_translator($usual_duration) unless $c->param('duration') =~ /[a-z0-9A-Z]/;
$c->param('uuid' => $uuid);
#&subs::setting_setter({ app => $app, setting => 'duration', value => $c->param('duration'), timestamp => $timestamp }) unless $usual_duration;
my $unit = $c->param('unit');
my $quantity = $c->param('quantity');
if ($quantity =~ /[a-zA-Z]/) {
my $gunit = $quantity;
$gunit =~ s/[^a-zA-Z]//gi;
$unit = $gunit if grep { $_ eq $gunit } keys %{$gb::measures};
$quantity =~ s/[a-zA-Z]//gi;
}
my $manufacturer = $c->param('manufacturer');
my $project = $c->param('project');
my $camera = $c->param('camera') || 0;
my $feed = $c->param('feed');
my $notes = $c->param('notes');
$notes =~ s/\$/\\\$/gi;
my $digits = $c->param('digits');
my $mirror = $c->param('mirror');
my $file = $c->param('file');
my $mute = $c->param('mute');
my $words = $c->param('words');
my $time_definition = &subs::rightNow();
my $appointments;
my $results = &subs::db_query("select max(timestamp) as file,timestamp,notes,app,duration,type,status,amount,unit,account from appointments where app=? and timestamp <=? and type != 'note' order by timestamp", $app,$time_definition);
$appointments = $results->hashes;
$results = &subs::db_query("select min(timestamp) as file,timestamp,notes,app,duration,type,status,amount,unit,account from appointments where app=? and timestamp >=? and type != 'note' order by timestamp", $app,$time_definition);
push @{$appointments}, @{$results->hashes};
if (scalar @{$appointments} == 0) { $type = "add" };
my $pos = &subs::setting_grabber({ app => $app, setting => 'pos' } ) || 'idea';
$notes = &subs::note_encrypter($c->session('suds'),$notes) if $notes;
my ($status,$announced_time);
my $warranty_holder = $timestamp;
$warranty_holder = $server_time if $server_time > $timestamp;
my $warranty = &subs::ago_calc(($c->param('warranty') || &subs::setting_grabber({ app => $app, setting => 'warranty' })),$warranty_holder);
$returner->{'warranty'} = $warranty;
my $usual_schedule = &subs::setting_grabber({ app => $app, setting => 'schedule' });
my $schedule = &schedule_maker($c,$c->param('schedule'),$timestamp);
$schedule = &schedule_maker($c,$usual_schedule,$timestamp) unless $c->param('schedule');
my $seen = 'yes';
if ($timestamp > &subs::rightNow() + 1000) {
$seen = undef;
}
if ($type eq 'start' || $type eq 'record') {
my $jdata;
if ($type eq 'record') {
my $recording_type = &subs::setting_grabber({ app => $app, setting => 'record' });
my $dat = { recorder => $recording_type };
if ($recording_type eq 'video') {
$seen = undef;
$dat->{'camera'} = $camera;
}
elsif ($recording_type eq 'audio') {
$seen = undef;
}
elsif ($recording_type eq 'screen') {
$seen = undef;
}
elsif ($recording_type eq 'video_front') {
$dat->{'camera'} = $camera;
}
elsif ($recording_type eq 'security') {
&record_video({ app => $app, uuid => $uuid, timestamp => $timestamp }) if $seen eq 'yes';
}
else {
&record_audio({ app => $app, uuid => $uuid, timestamp => $timestamp }) if $seen eq 'yes';
}
$jdata = encode_json $dat;
}
&subs::intelligent_automation_toggle({ appt_uuid => $uuid, app => $app, 'state' => 'on', timestamp => $timestamp });
my ($model,$options,$jmodel,$joptions) = &subs::usual_appointment_maker({
app => $app,
uuid => $uuid,
timestamp => $timestamp,
$duration => (abs $duration) * -1,
type => $type
},{
project => $project
});
if (!$unit && $model->{'unit'}) {
$unit = $model->{'unit'};
}
elsif ($init->{'unit'}) {
$unit = $init->{'unit'};
}
if (!$quantity && $model->{'quantity'}) {
$quantity = $model->{'quantity'};
}
elsif ($init->{'quantity'}) {
$init->{'quantity'};
}
if (!$manufacturer && $model->{'manufacturer'}) {
$manufacturer = $model->{'manufacturer'};
}
elsif ($init->{'manufacturer'}) {
$manufacturer = $init->{'manufacturer'};
}
my $source_uuid;
foreach my $qo ( qw/model option/ ) {
my $mo = &subs::db_select($qo, undef, { name => $app })->hashes;
foreach my $ao ( @{$mo} ) {
my $began = &subs::db_query('select * from appointments where app=? and (type=? or type=?) and timestamp <= ? order by timestamp desc limit 1',$ao->{'app'},'record','start',$timestamp)->hashes;
$source_uuid = $began->[0]->{'uuid'};
}
}
my $stop_timestamp = $c->param('duration') =~ /[a-zA-Z0-9]/ ? $timestamp - ((abs $duration) * -1) : undef;
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
unit => $unit,
quantity => $quantity,
project => $project,
type => $type,
status => $status,
duration => (abs $duration) * -1,
start_notes => $notes,
server_time => $server_time,
file => $file,
data => $jdata,
'pos' => $pos,
warranty => $warranty + (abs $duration),
source => $source,
uuid => $uuid,
model => $jmodel,
options => $joptions,
seen => $seen,
source_uuid => $source_uuid,
stop_timestamp => $stop_timestamp,
browser_tab_id => $browser_tab_id
});
&subs::setting_setter({ app => $app, setting => 'toggle', value => 'on' }) if $seen eq 'yes';
if ($stop_timestamp) {
&subs::intelligent_automation_toggle({ appt_uuid => $uuid, app => $app, 'state' => 'off', timestamp => $stop_timestamp + 3000 });
}
}
elsif ($type eq 'stop') {
my $recording_type = &subs::setting_grabber({ app => $app, setting => 'record' });
my $began = &subs::db_query('select * from appointments where app=? and (type=? or type=? or type = ? or type = ? or type = ?) and timestamp <= ? and stop_seen is null order by timestamp asc limit 1',
$app,'record','start','video', 'audio', 'screen', $timestamp);
my $old_appts = $began->hashes;
foreach my $o ( @{$old_appts} ) {
# next;
my $timestamp1 = $o->{'timestamp'};
$uuid = $o->{'uuid'};
$c->param('uuid' => $uuid);
if ($o->{'type'} eq 'record') {
my $data = eval { return decode_json $o->{'data'} } || {};
if ($data->{'recorder'} eq 'security') {
if ($seen eq 'yes') {
&record_video_stop({ app => $app, timestamp => $timestamp1, uuid => $o->{'uuid'} }) if $o->{'uuid'};
next;
}
else { $type = 'record'; };
}
elsif ($data->{'recorder'} eq 'system') {
if ($seen eq 'yes') {
&record_audio_stop({ app => $app, timestamp => $timestamp1, uuid => $o->{'uuid'} }) if $o->{'uuid'};
next;
}
else { $type = 'record'; };
}
elsif ($seen eq 'yes') {
&Websocket::send('music', { console => 'jpStop(\'' . $o->{'app'} . '\',\'' . $data->{'recorder'} . '\',\'' . $o->{'uuid'} . '\');' });
}
}
unless ($c->param('duration')) {
$duration = $timestamp1 - $timestamp;
my $all_durations = &subs::db_query('select * from appointments where app=? and type=? order by server_time DESC LIMIT 40',$app,'stop')->hashes;
my $total_durations = abs $duration;
if ($o->{'end_notes'}) {
my $n = &subs::note_decrypter($c->session('suds'), $o->{'end_notes'}, $o->{'ost'});
$n .= "\n" . &subs::note_decrypter($c->session('suds'), $notes);
$notes = &subs::note_encrypter($c->session('suds'), $n);
}
foreach my $ad ( @{$all_durations} ) {
$total_durations += abs $ad->{'duration'};
}
my $new_duration = $total_durations / ( scalar @{$all_durations} + 1);
&subs::setting_setter({ app => $app, setting => 'duration', value => &subs::duration_sayer($new_duration / 1000 ) });
}
else {
$duration = (abs $duration) * -1;
}
if ($o->{'type'} eq 'start' || $o->{'type'} eq 'record') {
$type = 'stop';
}
else {
$type = $o->{'type'};
}
if ($seen eq 'yes') {
&subs::setting_setter({ app => $app, setting => 'toggle', value => 'off' });
&subs::db_update('appointments', {
project => $project,
type => $type,
duration => $duration,
# timestamp => $timestamp,
end_notes => $notes,
server_time => $server_time,
app => $app,
'pos' => $pos,
warranty => $warranty,
source => $source,
stop_seen => $timestamp <= &subs::rightNow() + 1000 ? 'yes' : undef,
stop_timestamp => $timestamp,
}, {
app => $app,
timestamp => $timestamp1,
uuid => $o->{'uuid'}
});
}
else {
&subs::db_update('appointments', {
project => $project,
duration => $duration,
# timestamp => $timestamp,
end_notes => $notes,
server_time => $server_time,
app => $app,
'pos' => $pos,
warranty => $warranty,
source => $source,
stop_seen => $timestamp <= &subs::rightNow() + 1000 ? 'yes' : undef,
stop_timestamp => $timestamp >= &subs::rightNow() + 1000 ? $timestamp : undef,
}, {
app => $app,
timestamp => $timestamp1,
uuid => $o->{'uuid'}
});
}
&subs::intelligent_automation_toggle({ appt_uuid => $o->{'uuid'}, app => $app, 'state' => 'off', timestamp => $timestamp });
my $sources = &subs::db_select('appointments', undef, { source_uuid => $o->{'uuid'} })->hashes;
my $options = eval { return decode_json $o->{'options'} } || [];
my $model = eval { return decode_json $o->{'model'} } || {};
push @{$options}, $model if $model->{'uuid'};
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'start' ) {
my @current_option = grep { $_->{'name'} eq $so->{'app'} } @{$options};
my $co = $current_option[0];
my $dur = $so->{'timestamp'} - $timestamp;
my $ts = $timestamp;
if ($co->{'delay_stop'}) {
my $t = &subs::time_abbrev_translator($co->{'delay_stop'});
$ts = $ts + $t;
$dur = $dur + $t;
}
my $so_data = { stop_timestamp => $ts, duration => $dur, server_time => $server_time };
if ($ts <= &subs::rightNow()) {
$so_data->{'type'} = $type;
$so_data->{'stop_seen'} = 'yes';
}
&subs::db_update('appointments', $so_data, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&subs::intelligent_automation_toggle({ appt_uuid => $so->{'uuid'}, app => $so->{'app'}, 'state' => 'off', timestamp => $ts });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $o->{'uuid'} .'\');'});
}
}
elsif ($type eq 'cancel') {
my $timestamp1 = &subs::db_select('appointments', ['uuid','timestamp'], { app => $app, type => 'start' })->hash;
$uuid = $timestamp1->{'uuid'};
$duration = $timestamp - $timestamp1->{'timestamp'};
&subs::intelligent_automation_toggle({ appt_uuid => $uuid, app => $app, 'state' => 'off', timestamp => $timestamp1->{'timestamp'} });
&subs::db_update('appointments', {
type => 'cancel',
'pos' => $pos,
warranty => $warranty,
source => $source,
server_time => $server_time
},
{
app => $app,
project => $project,
timestamp => $timestamp1->{'timestamp'},
uuid => $uuid,
type => 'start'
});
my $sources = &subs::db_select('appointments', undef, { source_uuid => $uuid })->hashes;
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'start' ) {
&subs::db_update('appointments', { type => $type, duration => $duration, server_time => $server_time }, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&subs::intelligent_automation_toggle({ appt_uuid => $so->{'uuid'}, app => $so->{'app'}, 'state' => 'off', timestamp => $so->{'timestamp'} });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
}
elsif ($type =~ 'reset' || $type =~ 'usual') {
unless ($c->param('duration')) {
my $udur = &subs::db_query('select duration from appointments where app=? and type=? order by timestamp DESC LIMIT 20',$app,'stop')->hashes;
my $ucount = scalar @{$udur};
my $utotal = 0;
if ($ucount > 1) {
foreach my $u ( @{$udur} ) {
$utotal += $u->{'duration'};
}
$duration = $utotal / $ucount;
}
else {
my $sduration = eval { return &subs::db_select('settings', ['value'], {app => $app, setting => 'duration', device => $device })->hash->{value} };
if ($sduration && $duration == undef) {
$sduration = &subs::time_abbrev_translator($sduration);
$duration = $sduration;
}
}
}
if ($duration < 0) {
$duration = $duration * -1;
}
my ($model,$options,$jmodel,$joptions) = &subs::usual_appointment_maker({
app => $app,
uuid => $uuid,
timestamp => $timestamp,
$duration => (abs $duration),
type => $type
}, {
project => $project
});
if (!$unit && $model->{'unit'}) {
$unit = $model->{'unit'};
}
elsif ($init->{'unit'}) {
$unit = $init->{'unit'};
}
if (!$quantity && $model->{'quantity'}) {
$quantity = $model->{'quantity'} ;
}
elsif ($init->{'quantity'}) {
$quantity = $init->{'quantity'};
}
if (!$manufacturer && $model->{'manufacturer'}) {
$manufacturer = $model->{'manufacturer'};
}
elsif ($init->{'manufacturer'}) {
$manufacturer = $init->{'manufacturer'};
}
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
unit => $unit,
quantity => $quantity,
project => $project,
type => $type,
status => 'usual',
duration => $duration,
start_notes => $notes,
server_time => $server_time,
file => $file,
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
model => $jmodel,
options => $joptions,
browser_tab_id => $browser_tab_id
});
}
elsif ($type =~ 'sms' && $device eq 'mobile') {
my $data = {};
($data->{'digits'},$data->{'message'}) = &sms_message_send($digits,$c->param('notes'));
$data = &subs::note_encrypter($c->{'suds'}, encode_json $data);
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
unit => $unit,
project => $project,
type => 'sms',
status => 'sms',
duration => '500',
data => $data,
start_notes => $notes,
server_time => $server_time,
file => $file,
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
});
}
elsif ($type eq 'renew') {
my $appt_db = &subs::db_query('select * from appointments where app = ?',$app);
my $sames = $appt_db->hashes;
my $app_warranty = &subs::ago_calc(&subs::setting_grabber({ app => $app, setting => 'warranty' }), $timestamp);
foreach my $same (@{$sames}) {
my $new_warranty = $app_warranty - $timestamp + $same->{'timestamp'};
&subs::db_update('appointments', {
warranty => $new_warranty,
server_time => &subs::rightNow()
},
{
app => $same->{'app'},
timestamp => $same->{'timestamp'},
server_time => $same->{'server_time'},
uuid => $same->{'uuid'}
});
my $websockets = &subs::db_query('select * from websockets where windows like ? and server_time > ? and windows is not null order by timestamp DESC',
'%app":"' . $app . '%', $server_time - 5000)->hashes;
if (scalar @{$websockets} > 0) {
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $same->{'uuid'} .'\');'});
}
}
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
unit => $unit,
project => $project,
type => 'renew',
start_notes => $notes,
server_time => $server_time,
file => $file,
duration => 3000,
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
});
}
elsif ($type eq 'delay') {
my $appt = &subs::db_select('appointments', undef, {app => $app, type => ['record','start'] }, { -desc => 'timestamp' })->hashes->[0];
my $timestamp1 = $appt->{'timestamp'};
$duration = $appt->{'duration'} ? $appt->{'duration'} : $timestamp - $appt->{'timestamp'};
my $stop_timestamp = $c->param('duration') =~ /[a-z0-9A-Z]/ ? $timestamp + (abs &subs::time_abbrev_translator($c->param('duration') )) : $appt->{'stop_timestamp'} ? $timestamp + (abs $duration): undef;
$uuid = $appt->{'uuid'};
&subs::db_update('appointments', {
unit => $unit,
project => $project,
type => 'start',
status => 'start',
timestamp => $timestamp,
notes => $notes,
server_time => $server_time,
file => $file,
duration => $duration,
'pos' => $pos,
warranty => $warranty,
source => $source,
seen => $seen,
stop_timestamp => $stop_timestamp,
stop_seen => $stop_timestamp && $stop_timestamp <= $server_time + 1000 ? 'yes' : undef
}, {
app => $app,
timestamp => $appt->{'timestamp'},
type => 'start',
uuid => $uuid
});
my $sources = &subs::db_select('appointments', undef, { source_uuid => $uuid })->hashes;
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'start' ) {
&subs::db_update('appointments', { type => 'start', timestamp => $timestamp, duration => $duration, server_time => $server_time }, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
}
elsif ($type eq 'pause') {
my $last = &subs::db_select('appointments', undef, {app => $app, type => 'start' })->hashes->[0];
my $timestamp1 = $last->{'timestamp'};
$uuid = $last->{'uuid'};
$duration = $timestamp - $timestamp1;
&subs::db_update('appointments', {
unit => $unit,
project => $project,
type => 'pause',
status => 'paused',
duration => $duration,
timestamp => $timestamp,
end_notes => $notes,
server_time => $server_time,
file => $file,
warranty => $warranty,
source => $source,
seen => $seen
}, {
app => $app,
timestamp => $timestamp1,
type => 'start',
'pos' => $pos,
uuid => $uuid
});
my $sources = &subs::db_select('appointments', undef, { source_uuid => $uuid })->hashes;
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
&subs::db_update('appointments', { type => 'pause', status => 'paused', timestamp => $timestamp, duration => $duration, server_time => $server_time }, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
elsif ($type eq 'resume') {
my $old = &subs::db_query('select * from appointments where app = ? and (type = ? or type = ?) order by timestamp DESC LIMIT 1', $app, 'stop','cancel')->hashes;
$duration = $c->param('duration') =~ /0-9a-zA-Z/ ? (abs $c->param('duration') * -1) : $timestamp - $old->[0]->{'timestamp'};
$uuid = $old->[0]->{'uuid'};
&subs::intelligent_automation_toggle({ appt_uuid => $uuid, app => $old->[0]->{'app'}, 'state' => 'on', timestamp => $old->[0]->{'timestamp'} });
&subs::db_update('appointments', {
type => 'start',
status => 'start',
notes => $notes,
unit => $unit,
project => $project,
server_time => $server_time,
file => $file,
'pos' => $pos,
warranty => $warranty,
source => $source,
seen => $seen,
server_time => $server_time,
duration => ((abs $duration) * -1),
stop_timestamp => $c->param('duration') =~ /[a-zA-Z0-9]/ ? $old->[0]->{'timestamp'} - ((abs &subs::time_abbrev_translator($c->param('duration'))) * -1) : undef,
stop_seen => undef
}, {
app => $app,
uuid => $old->[0]->{'uuid'}
}
);
my $sources = &subs::db_select('appointments', undef, { source_uuid => $uuid })->hashes;
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'stop' ) {
&subs::db_update('appointments', { type => 'start', server_time => $server_time }, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&subs::intelligent_automation_toggle({ appt_uuid => $so->{'uuid'}, app => $so->{'app'}, 'state' => 'on', timestamp => $so->{'timestamp'} });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
}
elsif ($type eq 'add') {
$project = eval { return &subs::db_select('settings', ['app'], { setting => 'pos', value => 'project' },{-desc => 'timestamp'})->hash->{app} } || 'project';
my $counter = &subs::db_query('select count(*) from appointments where app=?', $app);
my $count = $counter->hash->{'count(*)'};
if ($count == 0 && 1 == 0) {
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
unit => $unit,
project => $project,
type => 'config',
status => $status,
duration => $duration,
start_notes => $notes,
server_time => $server_time,
file => $file,
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
});
$returner->{'added'} = 'yes';
}
}
elsif ($type eq 'camera') {
my $jdata = encode_json { camera => $camera };
my $data = {
app => $app,
timestamp => $timestamp,
project => $project,
unit => $unit,
type => 'image',
data => $jdata,
notes => $notes,
server_time => $server_time,
file => '[]',
duration => '5000',
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
};
&subs::db_insert('appointments', $data);
if ($seen eq 'yes') {
my ($file,$ocr) = &take_picture($c,{ timestamp => $timestamp, camera => $camera, uuid => $uuid });
}
}
elsif ($type eq 'scan') {
my $scandata = {
timestamp => $timestamp,
feed => $feed,
uuid => $uuid,
app => $app,
source => $source
};
my $jdata = encode_json $scandata;
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
project => $project,
unit => $unit,
type => 'scan',
start_notes => $notes,
server_time => $server_time,
file => '[]',
data => $jdata,
duration => $duration,
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
});
if ($seen eq 'yes') {
my $file = &scan($c, $scandata);
}
}
elsif ($type eq 'telephone') {
&subs::db_insert('appointments', {
app => $app,
timestamp => $timestamp,
project => $project,
unit => $unit,
type => 'telephone',
start_notes => $notes,
server_time => $server_time,
file => $file,
duration => '5000',
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
browser_tab_id => $browser_tab_id
});
my $send_telephone = &send_telephone($app,$c->param('notes'));
}
else {
my $already_running = 0;
if ($type eq 'note') {
my $began = &subs::db_query('select * from appointments where app=? and (type=? or type=?) and timestamp <= ? and timestamp < ? order by timestamp desc limit 1',$app,'record','start',$timestamp,&subs::rightNow());
my $old_appts = $began->hashes;
foreach my $o ( @{$old_appts} ) {
my $n = &subs::note_decrypter($c->session('suds'), $o->{'notes'}, $o->{'ost'});
$n .= "\n" if $n =~ /[a-zA-Z0-9.,]/gi;
$n .= &subs::note_decrypter($c->session('suds'), $notes);
$notes = &subs::note_encrypter($c->session('suds'), $n);
$already_running = $o->{'uuid'};
}
}
if ($type eq 'video' || $type eq 'audio' || $type eq 'screen') { $seen = undef; }
my $stop_timestamp = $c->param('duration') =~ /[a-zA-Z0-9]/ ? $timestamp - ((abs $duration) * -1) : undef;
if ($already_running eq 0) {
my $db_data = {
app => $app,
timestamp => $timestamp,
project => $project,
unit => $unit,
type => $type,
start_notes => $notes,
server_time => $server_time,
file => $file,
duration => '5000',
'pos' => $pos,
warranty => $warranty,
source => $source,
uuid => $uuid,
seen => $seen,
stop_timestamp => $stop_timestamp,
browser_tab_id => $browser_tab_id
};
&subs::db_insert('appointments', $db_data);
}
else {
&subs::db_update('appointments', { notes => $notes, server_time => &subs::rightNow() }, { app => $app, uuid => $already_running });
$uuid = $already_running;
}
}
undef @appointments;
# my $appts = &log_reader({ app => $app, view => 'centre_view' });
if ($measure_is_open eq 'true' && ($type eq 'start' || $type eq 'usual')) {
&appt_measure_writer($c,{ app => $app, uuid => $uuid, timestamp => $timestamp });
}
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
my $todays_date = localtime()->strftime('%A %B %d %Y');
my $todays_time = localtime()->strftime('%I:%M%P');
# $appts->{'__stash'}->{'header'} = 'no';
my $commander;
# $commander = &subs::run_command($app,$appts->{$app}->{'setting'}->{'record'}) if $appts->{$app}->{'setting'}->{'record'} && $type =~ /record/;
# &Websocket::send('server', { app => $app, console => &subs::setting_grabber({ app => $app, setting => 'record' }), device => $device, timestamp => $timestamp }) unless $type eq 'stop';
# &Websocket::send('server', { app => $app, console => &subs::setting_grabber({ app => $app, setting => 'kill' }), device => $device, timestamp => $timestamp }) unless $type eq 'stop';
# &Websocket::send('server', { app => $app, console => &subs::setting_grabber({ app => $app, setting => 'command' }), device => $device, timestamp => $timestamp }) if $type eq 'command';
# $commander = &subs::run_command($appts->{$app}->{'setting'}->{'command'}) if $appts->{$app}->{'setting'}->{'command'} && $type =~ /command/;
# &subs::cache_delete({ app => $app, context => 'template' });
my $cv = ¢re_view_grabber({ c => $c, app => $app, timestamp => $timestamp });
&budget_runner($app);
&padlock_time_extender($c);
$returner->{'cv'} = $cv;
$returner->{'uuid'} = $uuid;
unless ($c->param('account') && $c->param('account') eq 'gallery' && &subs::setting_grabber({ app => 'me', setting => 'gallery_appts' }) eq 'off' ) {
# &Websocket::send('tab', { app => $app, window => $cv, timestamp => $timestamp });
}
&subs::file_encrypter({ app => $app, suds => $c->session('suds') });
return $returner;
}
post '/manager/configure/stop_all_appointments' => sub($c) {
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
my $ap = &subs::db_query('select * from appointments where type = ? or type = ? and timestamp <= ?', 'record','start',$timestamp);
my $appts = $ap->hashes;
foreach my $a ( @{$appts}) {
my $duration = $a->{'timestamp'} - $timestamp;
my $sq = &subs::db_query('select app,setting,value from settings where app = ? and setting=? and value != ?',$a->{'app'},'duration','');
my $old_appts = &subs::db_query('select * from appointments where type=? and app = ? order by timestamp DESC LIMIT 20', 'stop', $a->{'app'})->hashes;
my $sqsults = $sq->hashes;
if (scalar @{$old_appts} > 2) {
my $toa = 0;
foreach my $oa ( @{$old_appts} ) {
$toa += abs $oa->{'duration'};
}
$duration = $toa / @{$old_appts};
}
elsif (scalar @{$sqsults} > 0) {
$duration = &subs::time_abbrev_translator($sqsults->[-1]->{'value'});
if ($duration && $duration > 0) { $duration = $duration * -1; }
}
&subs::db_update('appointments', {
type => 'stop',
duration => $duration,
server_time => &subs::rightNow()
},{
server_time => $a->{'server_time'},
timestamp => $a->{'timestamp'},
app => $a->{'app'}
});
}
$c->render(text => 'ok');
};
get '/manager/transaction/autocomplete' => sub($c) {
my $attribute = $c->param('attribute');
my $value = $c->param('value');
my $app = $c->param('app');
my $list;
if ($attribute) {
my $query = 'select distinct(app),' . $attribute . ' from appointments where app=? and (type=? or type=?) and ' . $attribute . ' like ? and ' . $attribute . ' != \'\' order by server_time desc limit 5';
$list = &subs::db_query($query, $app, 'purchase','transaction', '%' . $value . '%')->hashes;
}
else {
my $query = 'select distinct(app) from appointments where app like ? order by server_time desc limit 5';
$list = &subs::db_query($query, '%' . $value . '%')->hashes;
}
foreach my $l ( @{$list} ) {
$l->{'formatted'} = &subs::format_name($l->{$attribute});
$l->{'unformatted'} = &subs::unformat_name($l->{$attribute});
}
$c->render('json' => $list);
};
get '/manager/transaction/autofill' => sub($c) {
my $name = &subs::unformat_name($c->param('name'));
my $app = &subs::unformat_name($c->param('app'));
my $movement = $c->param('movement');
my $raw_value = $c->param('value');
my $value = &subs::unformat_name($c->param('value'));
my $query = 'select ' . $name . ' from appointments where ' . $name . '=? and app=? and type=? and movement = ? order by timestamp DESC LIMIT 40';
my $probs = &subs::db_query($query,$value, $app,'transaction',$movement)->hashes;
my $returner = {};
foreach my $prob ( @{$probs} ) {
my $occurrences = 1;
if ($returner->{$prob->{$name}}) {
$occurrences = $returner->{$prob->{$name}}->{'occurrences'} + 1;
}
$returner->{$prob->{$name}} = {
unformatted => $prob->{$name},
formatted => &subs::format_name($prob->{$name}),
occurrences => $occurrences
};
}
my $probable = {};
if ($name eq 'quantity') {
if ($raw_value =~ /[a-zA-Z]/) {
my $gunit = $raw_value;
$gunit =~ s/[^a-zA-Z]//gi;
$probable->{'unit'} = $gunit if grep { $_ eq $gunit } keys %{$gb::measures};
}
}
foreach my $ret ( keys %{$returner} ) {
if ( $returner->{$ret}->{'occurrences'} > $probable->{'occurrences'} ) {
$probable = $returner->{$ret};
}
}
if (!$probable->{'unformatted'}) {
$probable->{'unformatted'} = &subs::unformat_name($raw_value);
}
if ($name eq 'item' || $name eq 'vendor' || $name eq 'manufacturer') {
my $a = $probable->{'unformatted'};
$a = $app unless $raw_value =~ /[a-zA-Z.,]/gi;
my $appts = &log_reader({ app => $a, view => 'centre_view' });
if ($appts->{$a}) {
foreach my $convert ( qw/app_measures packaging/ ) {
if (eval { $appts->{$a}->{'setting'}->{$convert} }) {
$appts->{$a}->{'setting'}->{$convert} = eval { return decode_json $appts->{$a}->{'setting'}->{$convert} } || [];
}
}
$appts->{$a}->{'setting'}->{'source_app'} = $app;
$probable->{'settings'} = $appts->{$a}->{'setting'};
foreach my $mo ( @{$appts->{$a}->{'model'}}, @{$appts->{$a}->{'option'}} ) {
$mo->{'characteristics'} = eval { return decode_json $mo->{'characteristics'} } || [];
if (my @oc = grep { $_->{'name'} eq 'option_category' } @{$mo->{'characteristics'}}) {
$mo->{'option_category'} = $oc[0]->{'value'};
}
else {
$mo->{'option_category'} = 'uncategorized';
}
}
if (scalar @{$appts->{$a}->{'model'}} > 0) {
$probable->{'models'} = $c->render_to_string(
template => 'apps/transaction/models',
settings => $appts->{$a}->{'setting'},
models => $appts->{$a}->{'model'},
l => $appts->{$a}->{'list'}->[0],
source => 'transaction',
);
}
if (scalar @{$appts->{$a}->{'option'}} > 0) {
$probable->{'options'} = $c->render_to_string(
template => 'apps/transaction/options',
settings => $appts->{$a}->{'setting'},
options => $appts->{$a}->{'option'},
option_categories => $appts->{$a}->{'option_category'},
l => $appts->{$a}->{'list'}->[0],
source => 'transaction',
);
}
}
else {
$probable = {};
}
}
if ($probable->{'unformatted'}) {
$probable->{'informations'} = [];
if ($movement eq 'income') {
my $invoices = &subs::db_query('select * from appointments where type=? and app = ? order by timestamp', 'invoice', $probable->{'unformatted'})->hashes;
@{$invoices} = grep { $_->{'status'} ne 'completed' } @{$invoices};
$probable->{'informations'} = $invoices;
}
elsif ($movement eq 'expense') {
my $purchases = &subs::db_query('select * from appointments where type=? and app = ? order by timestamp', 'purchase', $probable->{'unformatted'})->hashes;
@{$purchases} = grep { $_->{'status'} eq 'delivered' } @{$purchases};
$probable->{'informations'} = $purchases;
}
if (grep { $name eq $_ } qw/amount tax aux total/ ) {
if (&subs::price_formatter($value) ne &subs::price_formatter($probable->{'unformatted'})) {
$probable = {};
}
}
}
$c->render(json => $probable);
};
get '/manager/transaction/information' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $returner = { autofillers => ['vendor','item', 'manufacturer'] };
my $transaction = &subs::db_query('select * from appointments where uuid=?', $uuid)->hashes->[0];
if ($transaction) {
$transaction->{'data'} = eval { return decode_json $transaction->{'data'} };
$transaction->{'data'}->{'vendor'} = $transaction->{'app'} || &subs::setting_grabber({ app => 'me', setting => 'store_name' }) unless $transaction->{'data'}->{'vendor'};
foreach my $af ( @{$returner->{'autofillers'}} ) {
$transaction->{'data'}->{'formatted_' . $af } = &subs::format_name($transaction->{'data'}->{$af});
}
}
$returner->{'html'} = $c->render_to_string(
template => 'apps/information',
app => $transaction
);
$returner->{'transaction'} = $transaction;
$c->render(json => $returner);
};
get '/manager/transaction/history_retriever' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $query = 'select * from appointments where data is not null and type=? and app=? and timestamp < ? order by timestamp desc limit 1';
my $transactions = &subs::db_query($query, 'transaction', $app, $timestamp)->hashes->[0];
unless ($transactions->{'app'}) {
my $query = 'select * from appointments where data is not null and type=? and app=? and timestamp < ? order by timestamp desc limit 1';
$transactions = &subs::db_query($query, 'transaction', $app, &subs::rightNow())->hashes->[0];
}
$c->render(json => $transactions);
};
post '/manager/transaction/status' => sub($c) {
my $timestamp = $c->param('timestamp');
my $appt_uuid = $c->param('appt_uuid');
my $status = $c->param('status');
my $app = $c->param('app');
&subs::db_update('appointments', { status => $status }, { app => $app, uuid => $appt_uuid });
$c->render('text' => 'ok');
};
post '/manager/transaction/record' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $app = &subs::unformat_name($c->param('app'));
my $account = $c->param('account');
my $project = $c->param('project');
my $timestamp = ×tamp_adjuster($c);
my $server_time = &subs::rightNow();
my $duration = $c->param('duration') || 5000;
my $notes = &subs::note_encrypter($c->session('suds'),$c->param('notes'));
my $movement = $c->param('movement');
my $transaction_information = $c->param('transaction_information');
my $warranty = &subs::ago_calc($c->param('warranty') || '-7y' || &subs::setting_grabber({ app => $app, setting => 'warranty' }), $timestamp);
my $uuid = &subs::random_string_creator(40);
my $currency = $c->param('currency') || &subs::setting_grabber({ app => $app, setting => 'currency' });
my $has_totes = $c->param('has_totes');
my $has_tax = $c->param('has_tax');
my $manufacturer = &subs::unformat_name($c->param('manufacturer'));
my $vendor = &subs::unformat_name($c->param('vendor'));
my $record_vendor = $c->param('record_vendor');
my $unit = $c->param('unit');
my $amount = $c->param('amount');
my $tax = $c->param('tax');
my $aux = $c->param('aux');
my $aux_description = $c->param('aux_description');
my $total = $c->param('total');
my $item = &subs::unformat_name($c->param('item'));
my $state = $c->param('state');
my $quantity = $c->param('quantity');
my $model = &subs::db_query('select * from model where uuid=?',$c->param('model'))->hashes->[0];
my $transfer_amount = $c->param('transfer_amount');
my $to_account = $c->param('to_account');
my $jtransactions = $c->param('transactions');
my $transactions = eval { return decode_json $c->param('transactions') } || {};
if ($quantity =~ /G$/gi) {
$quantity =~ s/G$//gi;
}
my $returner = { uuid => $uuid, app => $app, timestamp => $timestamp, navigation => 'once' };
if ($movement eq 'income' || $movement eq 'expense') {
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
notes => $notes,
total => $transactions->{$movement}->{'totals'}->{'total'} || $total,
amount => $transactions->{$movement}->{'totals'}->{'amount'} || $amount,
tax => $transactions->{$movement}->{'totals'}->{'tax'} || $tax,
aux => $transactions->{$movement}->{'totals'}->{'aux'} || $aux,
type => 'transaction',
aux_description => $aux_description,
duration => $duration,
account => $account,
project => $project,
warranty => $warranty,
item => $item,
model => $model->{'uuid'},
manufacturer => $manufacturer,
vendor => $vendor,
quantity => $quantity,
movement => $movement,
'state' => $state,
has_tax => $has_tax,
has_totes => $has_totes,
unit => $unit,
uuid => $uuid,
data => $jtransactions,
currency => $currency
};
&appointment_writer($c,$write);
if ($transaction_information && $transaction_information ne '' && $vendor) {
my $inv = &subs::db_query('select * from appointments where app=? and uuid=?', $vendor, $transaction_information)->hashes->[0];
if ($inv) {
my $data = eval { return decode_json $inv->{'data'} };
unless ($data->{'payments'}) {
$data->{'payments'} = [];
}
push @{$data->{'payments'}}, { account => $account, uuid => &subs::random_string_creator(12), appt_uuid => $uuid, amount => $total, timestamp => $timestamp, server_time => &subs::rightNow(), };
$data->{'numbers'}->{'balance'} = $data->{'numbers'}->{'balance'} - $total;
$inv->{'data'} = encode_json $data;
$inv->{'server_time'} = &subs::rightNow();
if ($data->{'numbers'}->{'balance'} == 0) {
$inv->{'status'} = 'completed';
}
&subs::db_update('appointments', $inv, { uuid => $inv->{'uuid'}, app => $inv->{'app'} });
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $vendor . '\',\'' . $inv->{'uuid'} .'\');'});
}
}
if ($vendor && $record_vendor eq 'on') {
my $init = &subs::settings_grabber({ app => $vendor });
$init = &subs::setting_initializer($vendor . ' vendor',$timestamp) unless $init->{'pos'};
$vendor = $init->{'app'};
&appointment_writer($c, {
timestamp => $timestamp,
type => 'purchase',
account => $account,
project => $project,
warranty => $warranty,
duration => $duration,
app => $vendor,
manufacturer => $manufacturer,
quantity => $quantity,
unit => $unit,
movement => $movement,
item => $item,
uuid => &subs::random_string_creator(20),
total => $transactions->{$movement}->{'totals'}->{'total'} || $total,
amount => $transactions->{$movement}->{'totals'}->{'amount'} || $amount,
tax => $transactions->{$movement}->{'totals'}->{'tax'} || $tax,
aux => $transactions->{$movement}->{'totals'}->{'aux'} || $aux,
source_uuid => $uuid
});
}
foreach my $t ( keys %{$transactions->{$movement}} ) {
unless ($t eq 'totals') {
my $tr = $transactions->{$movement}->{$t};
if ($tr->{'manufacturer'} && $tr->{'record_manufacturer'} eq 'on') {
my $init = &subs::setting_initializer($tr->{'manufacturer'} . ' manufacturer',$timestamp);
$manufacturer = $init->{'app'};
&appointment_writer($c, {
timestamp => $timestamp,
type => 'purchase',
account => $account,
project => $project,
warranty => $warranty,
duration => $duration,
app => $manufacturer,
manufacturer => $manufacturer,
quantity => $tr->{'quantity'},
unit => $tr->{'unit'},
movement => $movement,
item => $tr->{'item'},
vendor => $vendor,
uuid => &subs::random_string_creator(18),
amount => $tr->{'amount'},
tax => $tr->{'tax'},
aux => $tr->{'aux'},
total => $tr->{'total'},
source_uuid => $uuid,
currency => $currency
});
}
if ($tr->{'item'} && $tr->{'record_item'} eq 'on') {
my $item = $tr->{'item'};
my @items = split ',', $item;
foreach my $i ( @items ) {
my $purchase = {
timestamp => $timestamp,
type => 'purchase',
account => $account,
project => $project,
warranty => $warranty,
duration => $duration,
app => $i,
amount => $tr->{'amount'} / scalar @items,
tax => $tr->{'tax'} / scalar @items,
aux => $tr->{'aux'} / scalar @items,
total => $tr->{'total'} / scalar @items,
vendor => $vendor,
manufacturer => $tr->{'manufacturer'},
uuid => $uuid . '-' . $t . '-' . scalar @items,
has_tax => $tr->{'has_tax'},
has_totes => $tr->{'has_totes'},
'state' => $tr->{'state'} || $state,
quantity => $tr->{'quantity'},
unit => $tr->{'unit'},
source_uuid => $uuid,
currency => $currency
};
&appointment_writer($c, $purchase);
}
}
}
}
my ($db,$database,$sql) = &subs::database_grabber();
if ($model->{'uuid'}) {
my $model_data = eval { return decode_json $model->{'inventory'} } || $gb::inventory_states;
my $new_quantity = ($model->{'inventory'} || 0) + $quantity;
# &subs::db_query('update models set inventory=? where uuid=?', $new_quantity, $model->{'uuid'});
}
}
elsif ($movement eq 'transfer') {
my $write1_uuid = &subs::random_string_creator(20);
my $write2_uuid = &subs::random_string_creator(20);
my $write1 = {
app => $app,
amount => $transfer_amount * -1,
total => $transfer_amount * -1,
type => 'transaction',
movement => 'transfer',
timestamp => $timestamp,
server_time => &subs::rightNow(),
account => $account,
notes => $notes,
uuid => $write1_uuid,
warranty => $warranty,
data => $jtransactions,
source_uuid => $write2_uuid,
currency => $currency
};
my $write2 = {
app => $app,
amount => $transfer_amount,
total => $transfer_amount,
type => 'transaction',
movement => 'transfer',
timestamp => $timestamp,
server_time => &subs::rightNow(),
account => $to_account,
notes => $notes,
uuid => $write2_uuid,
warranty => $warranty,
source_uuid => $write1_uuid,
currency => $currency
};
&subs::db_insert('appointments', $write1);
&subs::db_insert('appointments', $write2);
}
elsif ($movement eq 'inventory') {
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
notes => $notes,
duration => $duration,
total => $total,
amount => $amount,
total => $amount,
type => 'transaction',
account => $account,
project => $project,
warranty => $warranty,
item => $item,
model => $model->{'uuid'},
quantity => $quantity,
movement => $movement,
'state' => $state,
unit => $unit,
uuid => $uuid,
data => $jtransactions,
currency => $currency
};
&subs::db_insert('appointments', $write);
}
undef @appointments;
my $appts = &log_reader({ app => $app, view => 'centre_view' });
# &appt_measure_writer($c,{ app => $app, uuid => $uuid, timestamp => $timestamp });
my $header = &subs::appt_header_printer({ appts => $appts, app => $app, timestamp => $timestamp });
my $content = $c->render_to_string(
template => 'appointment_wrapper',
appointments => [ $app ],
appts => $appts,
timestamp => $timestamp,
device => $device,
header => $header,
from => 'transaction',
config => &subs::config_reader(),
measures => $gb::measures
);
# &subs::cache_delete({ app => $app, context => 'template' });
my $cv = ¢re_view_grabber({ c => $c, app => $app, timestamp => $timestamp });
# &Websocket::send('tab', { app => $app, window => $cv, timestamp => $timestamp });
&budget_runner($app);
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
$returner->{'cv'} = '';#&window_maker({ user_agent => $c->param('user_agent'), app => $app, contents => $content }, $timestamp);
$c->render(json => $returner);
};
sub appt_measure_writer($c,$data) {
my $app = $data->{'app'};
my $timestamp = $data->{'timestamp'} || &subs::rightNow();
my $measure = $data->{'measure'};
my $value = $data->{'value'};
my $remote_address = $data->{'remote_address'};
my $setting_only = $c->param('setting_only');
my $uuid = $data->{'uuid'};
my $settings = &subs::settings_grabber({ app => $app, settings => [ 'app_measures', 'duration' ] });
my $app_measure = eval { return decode_json $settings->{'app_measures'} } || {};
my %appt_measure = %{$app_measure};
my $appt_measure = \%appt_measure;
if ($measure) {
if ($appt_measure->{$measure}->{'unit'} && ($appt_measure->{$measure}->{'type'} eq 'range' || $appt_measure->{$measure}->{'type'} eq 'number')) {
if ($value =~ /([a-zA-Z])/gi) {
my $uom = &subs::format_name($1);
my $formula = $value . ' to ' . $appt_measure->{$measure}->{'unit'};
my ($fo,$ev,$uom,$format) = &formula_calculator($formula);
$value = eval($ev);
$value =~ s/[a-zA-Z]//gi;
}
}
$app_measure = { $measure => $value, ts => $timestamp };
$appt_measure->{$measure}->{'value'} = $value;
my $ameasure = encode_json $appt_measure;
&subs::setting_setter({ app => $app, setting => 'app_measures', value => $ameasure });
}
if ( scalar keys %{$app_measure} > 0 && $setting_only ne 'yes') {
if (!$uuid) {
my $ago_timestamp = &subs::ago_calc($settings->{'duration'}, $timestamp);
my $after_timestamp = &subs::ago_calc('-5m', $timestamp);
my $appt = &subs::db_query('select * from appointments where app=? and type=? and timestamp < ? and timestamp >=? order by timestamp desc limit 1', $app, 'measure',
$after_timestamp, $ago_timestamp)->hashes->[0];
if ($appt->{'uuid'} =~ /[A-Za-z0-9]/) {
$uuid = $appt->{'uuid'};
}
}
if ($uuid) {
foreach my $am ( keys %{$app_measure} ) {
$app_measure->{$am} = $appt_measure->{$am}->{'value'};
}
$app_measure->{'uuid'} = &subs::random_string_creator(10);
$app_measure->{'ts'} = $timestamp || &subs::rightNow();
my $ca = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app })->hashes->[0];
my $car = eval { return decode_json $ca->{'measures'} } || [];
push @{$car}, $app_measure;
my $jcar = encode_json $car;
&subs::db_update('appointments', { measures => $jcar, server_time => &subs::rightNow() }, { uuid => $uuid, app => $app });
}
else {
$app_measure->{'uuid'} = &subs::random_string_creator(10);
$app_measure->{'ts'} = &subs::rightNow();
my $car = [];
push @{$car}, $app_measure;
my $jcar = encode_json $car;
my $data = {
app => $app,
timestamp => $timestamp,
type => 'measure',
duration => 1000,
measures => $jcar
};
my $appt = &appointment_writer($c,$data);
$uuid = $appt->{'uuid'};
}
my $state = $app_measure->{$measure};
if ($appt_measure->{$measure}->{'min'} && $appt_measure->{$measure}->{'max'}) {
my $total = $appt_measure->{$measure}->{'max'} - $appt_measure->{$measure}->{'min'};
my $state_total = $state - $appt_measure->{$measure}->{'min'};
$state = $state_total / $total * 100;
}
if ($data->{'source'} eq 'embedded') {
&Websocket::send('tab', { console => '$(\'.appointment[app="' . $app . '"]\').find(\'.app_measure[measure="' . $measure . '"]\').val(\'' . $app_measure->{$measure} . '\');' });
}
&subs::intelligent_automation_toggle({ appt_uuid => $uuid, app => $app, 'state' => $state, measurement => $app_measure->{$measure}, measure => $measure, timestamp => $timestamp, remote_address => $remote_address });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
&Websocket::send('tab', { console => 'continent_record({\'uuid\':\'' . $uuid . '\', \'app\':\'' . $app .'\',\'purpose\':\'app\',\'timestamp\':\'' . $timestamp . '\',\'navigation\':"once" });' });
}
}
post '/manager/app_measures' => sub ($c) {
my $app = $c->param('app');
my $measure = $c->param('measure');
my $value = $c->param('value');
my $server_time = &subs::rightNow();
my $measures = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'app_measures' }) } || {};
my $setting_only = $c->param('setting_only');
my $just_one = $c->param('just_one');
my $timestamp = ×tamp_adjuster($c);
unless ( eval { %{$measures->{$measure}} } ) {
$measures->{$measure} = {};
}
$measures->{$measure}->{'value'} = $value;
if ($value == 0) { $value = "0"; }
my $jmeasures = encode_json $measures;
unless ($just_one) {
&subs::setting_setter({ app => $app, setting => 'app_measures', value => $jmeasures });
}
my $running_appts = &subs::db_query('select uuid from appointments where (type = ? or type = ?) and app = ? and timestamp < ? ORDER BY timestamp LIMIT 1', 'record', 'start', $app, $server_time )->hashes;
if (scalar @{$running_appts} > 0) {
foreach my $ra ( @{$running_appts} ) {
&appt_measure_writer($c,{ app => $app, uuid => $ra->{'uuid'}, measure => $measure, value => $value, timestamp => $timestamp });
&Websocket::send('tab', { console => '$(\'.appointment[app="' . $app . '"]\').find(\'.app_measure[measure="' . $measure . '"]\').val(\'' . $value . '\');' }) if $setting_only ne 'yes';
}
}
else {
&appt_measure_writer($c, { app => $app, measure => $measure, value => $value, timestamp => $timestamp });
&Websocket::send('tab', { console => '$(\'.appointment[app="' . $app . '"]\').find(\'.app_measure[measure="' . $measure . '"]\').val(\'' . $value . '\');' }) if $setting_only ne 'yes';
}
$c->render(json => { measures => $measures });
};
post '/manager/configure/app_measure_configuration_adder' => sub($c) {
my $app = $c->param('app');
my $amway = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'app_measures' }) } || {};
$amway->{'new_measure'} = {};
my $jamway = encode_json $amway;
&subs::setting_setter({ app => $app, setting => 'app_measures', value => $jamway });
$amway->{'header'} = join ',', keys %{$amway};
my $appts = &log_reader({ app => $app, view => 'appointment_display' });
my $measures = eval { return decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
$appts->{$app}->{'setting'}->{'measures'} = join ',', keys %{$measures};
$appts->{$app}->{'setting'}->{'app_measures'} = $measures;
$amway->{'config'} = $c->render_to_string(
template => 'configure/app_measures',
settings => $appts->{$app}->{'setting'},
a => $app,
b => 'app_measures'
);
$amway->{'app_measure'} = $c->render_to_string(
template => 'apps/app_measures',
settings => $appts->{$app}->{'setting'},
a => $app
);
$c->render('json' => $amway);
};
post '/manager/configure/app_measure_configurator' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $measure = &subs::unformat_name($c->param('measure'));
my $setting = &subs::unformat_name($c->param('setting'));
my $value = $c->param('value');
my $oldvalue = $c->param('oldvalue');
my $amway = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'app_measures' }) } || {};
$amway->{$measure} = {} unless $amway->{$measure};
if ($setting eq 'options') {
my @value = split ',', $value;
$value = \@value;
}
foreach my $k ( keys %{$amway} ) {
unless ( $k =~ /[a-zA-Z0-9.]/gi ) {
$amway->{$k} = undef;
}
}
if ($setting eq 'measure' && $value =~ /[a-zA-Z0-9]/gi) {
$value = &subs::unformat_name($value);
my $changing = 0;
my $appointments = &subs::db_query('select * from appointments where app=? and measures is not null', $app)->hashes;
foreach my $apps ( @{$appointments} ) {
my $j = $apps->{'measures'};
my $app_changed = 0;
my $meas = eval { return decode_json $j } || [];
if (scalar @{$meas} > 0) {
$changing = 1;
foreach my $m ( @{$meas} ) {
if ($m->{$oldvalue}) {
$m->{$value} = $m->{$oldvalue};
delete $m->{$oldvalue};
$app_changed = 1;
}
}
if ($app_changed == 1) {
my $jam = encode_json $meas;
&subs::db_update('appointments', { server_time => &subs::rightNow(), measures => $jam }, { uuid => $apps->{'uuid'}, app => $apps->{'app'}, ost => $apps->{'ost'} });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $apps->{'uuid'} .'\');'});
}
}
}
if ($changing == 1) {
$amway->{$value} = $amway->{$oldvalue};
delete $amway->{$oldvalue};
}
}
else {
$amway->{$measure}->{$setting} = $value;
}
foreach my $k ( keys %{$amway} ) {
unless ( $k =~ /[a-zA-Z0-9.]/gi ) {
delete $amway->{$k};
}
}
my $jamway = encode_json $amway;
&subs::setting_setter({ app => $app, setting => 'app_measures', value => $jamway });
$amway->{'header'} = join ',', keys %{$amway};
my $appts = &log_reader({ app => $app, view => 'appointment_display' });
my $measures = eval { return decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
$appts->{$app}->{'setting'}->{'measures'} = join ',', keys %{$measures};
$appts->{$app}->{'setting'}->{'app_measures'} = $measures;
$amway->{'config'} = $c->render_to_string(
template => 'configure/app_measures',
settings => $appts->{$app}->{'setting'},
a => $app,
b => 'app_measures'
);
$amway->{'app_measure'} = $c->render_to_string(
template => 'apps/app_measures',
settings => $appts->{$app}->{'setting'},
a => $app
);
$c->render('json' => $amway);
};
post '/manager/app_measure_delete' => sub($c) {
my $app = $c->param('app');
my $app_uuid = $c->param('app_uuid');
my $uuid = $c->param('uuid');
my $appts = &subs::db_select('appointments', undef, { uuid => $app_uuid, app => $app })->hashes;
my $am = eval { return decode_json $appts->[0]->{'measures'} } || [];
@{$am} = grep { $_->{'uuid'} ne $uuid } @{$am};
my $jam = encode_json $am;
&subs::db_update('appointments', { measures => $jam, server_time => &subs::rightNow() }, { uuid => $app_uuid, app => $app, ost => $appts->[0]->{'ost'} });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $app_uuid .'\');'});
$c->render('text' => 'ok');
};
post '/manager/configure/packaging/save' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $name = $c->param('name');
my $value = $c->param('value');
my $uuid = $c->param('uuid');
my $packaging = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'packaging' }) } || {};
$packaging->{$uuid}->{$name} = $value;
my $jpack = encode_json $packaging;
&subs::setting_setter({ app => $app, value => $jpack, setting => 'packaging' });
my $html = $c->render_to_string(
template => 'configure/packaging',
settings => { app_packaging => $packaging }
);
$c->render(json => { packaging => $packaging, html => $html });
};
post '/manager/configure/packaging/delete' => sub($c) {
my $app = $c->param('app');
my $uuid = $c->param('uuid');
my $packaging = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'packaging' }) } || {};
delete $packaging->{$uuid};
my $jpack = encode_json $packaging;
&subs::setting_setter({ app => $app, value => $jpack, setting => 'packaging' });
my $html = $c->render_to_string(
template => 'configure/packaging',
settings => { app_packaging => $packaging }
);
$c->render(json => { packaging => $packaging, html => $html });
};
get '/manager/transaction/movement' => sub($c) {
my $movement = $c->param('movement');
my $app = $c->param('app');
&subs::setting_setter({ app => $app, setting => 't_movement', value => $movement });
my $appts = &log_reader({ app => $app, view => 'centre_view' });
my $informations = [];
my $html = '
' .
$c->render_to_string(
template => 'apps/transaction/' . $movement,
app => {},
appts => $appts,
a => $app,
) . '';
$c->render(json => { html => $html, app => $app });
};
post '/manager/inventory/evaluate' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $returner = { localtimes => {} };
my $timeslots = [ 's','m','h','mday','M','y','wday','yday','isdst'];
my $appts = [];
if ($app) {
$appts = &subs::db_select('appointments', undef, { app => $app })->hashes;
}
else {
$appts = &subs::db_select('appointments')->hashes;
}
my $evaluation = { timeslots => {} };
foreach my $appt ( @{$appts} ) {
my @time = localtime($appt->{'timestamp'} / 1000);
$appt->{'localtime'} = \@time;
for (my $n = 0; $n < scalar @{$timeslots}; $n++) {
my $t = $time[$n];
push @{$returner->{'localtimes'}->{$timeslots->[$n]}->{$t}}, $appt;
$evaluation->{'timeslots'}->{$timeslots->[$n]}->{$t} = scalar @{$returner->{'localtimes'}->{$timeslots->[$n]}->{$t}};
}
}
&subs::cache_set({ app => $app || '__president', context => 'evaluation', warranty => '-6M' }, $evaluation);
$c->render(json => $returner);
};
get '/manager/inventory/information' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $scope = $c->param('scope');
my $x = $c->param('x');
my $y = $c->param('y');
my $start_timestamp = $c->param('start_timestamp');
my $end_timestamp = $c->param('end_timestamp');
my $returner = {
scope => $scope,
timestamp => $timestamp,
app => $app
};
$returner->{'details'} = &inventory_details($c, &subs::settings_grabber({ app => $app }));
$returner->{'html'} = $c->render_to_string(
template => 'apps/inventory_info',
scope => $scope,
timestamp => $timestamp,
app => $app,
'x' => $x,
'y' => $y,
start_timestamp => $start_timestamp,
end_timestamp => $end_timestamp,
details => $returner->{'details'}
);
$c->render(json => $returner);
};
get '/manager/inventory/details' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $s_scroll = $c->param('s_scroll');
if ($s_scroll != 0) {
&subs::setting_setter({ app => $app, setting => 's_scroll', value => $s_scroll });
}
my $settings = &subs::settings_grabber({ app => $app });
my $returner = &inventory_details($c, $settings);
$c->render(json => $returner);
};
sub inventory_details($c,$settings) {
my $app = $c->param('app');
my $server_time = &subs::rightNow();
my $timestamp = $c->param('timestamp');
my $appts = [];
if ($c->param('display')) {
$settings->{'s_display'} = $c->param('display');
$settings->{'s_movement'} = $c->param('movement');
$settings->{'s_scope_count'} = $c->param('scope_count');
$settings->{'s_visual'} = $c->param('visual');
$settings->{'s_calc'} = $c->param('calc');
$settings->{'s_lock'} = $c->param('lock');
}
unless ($settings->{'s_display'}) {
&subs::setting_setter({ app => $app, setting => 's_display', value => 'occurences'});
$settings->{'s_display'} = 'occurences';
}
$settings->{'s_movement'} = eval { decode_json $settings->{'s_movement'} } || ['all'];
$appts = &subs::db_query('select * from appointments where app = ? or model = ? order by timestamp', $app, $app)->hashes;
my $movements = [ 'all' ];
foreach my $a ( @{$appts} ) {
push @{$movements}, $a->{'type'} unless grep { $_ eq $a->{'type'} } @{$movements};
}
push @{$movements}, 'start' unless grep { $_ eq 'start' } @{$movements};
if ($settings->{'s_movement'} == undef || grep { $_ eq 'all' } @{$settings->{'s_movement'}} ) {
}
else {
my $new_appts = [];
foreach my $sm ( @{$settings->{'s_movement'}} ) {
push @{$new_appts}, grep { $_->{'type'} eq $sm } @{$appts};
}
$appts = $new_appts;
}
my @display_options;
foreach my $k ( keys %{$gb::budget_modes} ) {
my $formatted_name = &subs::format_name($k);
if ($k eq 'quantity') {
$formatted_name = $formatted_name . ' (' . $settings->{'unit'} . ')';
}
my $bm = { name => $k, formatted_name => $formatted_name };
push @display_options, $bm;
}
my $am = eval { return decode_json $settings->{'app_measures'} } || {};
foreach my $ameas ( keys %{$am} ) {
my $formatted_name = &subs::format_name($ameas);
if ($am->{$ameas}->{'unit'}) {
$formatted_name = $formatted_name . ' (' . $am->{$ameas}->{'unit'} . ')';
}
push @display_options, { name => $ameas, formatted_name => $formatted_name } unless grep { $_->{'name'} eq $ameas } @display_options;
}
my @time_scopes = ('next', 'this','last');
my @time_widths;
my @time_lengths = qw/minute hour day week month year/;
if ($settings->{'s_visual'} eq 'allocation') {
@time_scopes = undef;
for (my $n = 0; $n <= 366; $n++) {
push @time_scopes, $n;
}
@time_lengths = qw/second minute hour mday month year wday yday isdst/;
@time_widths = ( 60, 60, 24, 31, 12, 150, 7, 365, 2 );
}
else {
for (my $n = 2; $n <= 30; $n++) {
push @time_scopes, $n . 'last' if $n <= $settings->{'s_scope_count'};
unshift @time_scopes, $n . 'next' if $n <= $settings->{'s_scope_count'};
}
}
if ($c->param('scope')) {
my $scope = &subs::unformat_name($c->param('scope'));
my $return_n = 0;
for ( my $n = 0; $n <= scalar @time_lengths; $n++ ) {
if ( $time_lengths[$n] eq $scope ) { $return_n = $n - 1; }
if ($c->param('zone')) {
if ($return_n > 1) {
my @timey_widths = ( 60, 24, 7, 30, 12, 10 );
@time_scopes = ('this','last');
push @time_widths, $timey_widths[$return_n];
for (my $n = 2; $n <= $timey_widths[$return_n]; $n++) {
push @time_scopes, $n . 'last';
}
}
}
}
@time_lengths = grep { $_ eq $time_lengths[$return_n] } @time_lengths;
}
my @revised_time_scopes = @time_scopes;
my $returner = {
longest => $appts->[0],
shortest => $appts->[0],
betweens => [],
between_total => 0,
between_average => 0,
longest_between => {},
shortest_between => {},
first_seen => $appts->[0],
'last_seen' => $appts->[0],
first_recorded => {},
last_recorded => {},
average_duration => 0,
total_duration => 0,
total_occurences => 0,
settings => $settings,
scopes => \@time_scopes,
time_lengths => \@time_lengths,
time_widths => \@time_widths,
app => $app,
budget_status => {},
};
my $bmt = scalar grep { $_ eq $settings->{'s_display'} } keys %{$gb::budget_modes};
if ( scalar @{$appts} > 0 ) {
foreach my $a ( @{$appts} ) {
if ($a->{'measures'}) {
$a->{'measures'} = eval { return decode_json $a->{'measures'} } || [];
}
if (($a->{'type'} eq 'start' || $a->{'type'} eq 'record')) {
if ($a->{'timestamp'} < $server_time) {
$a->{'duration'} = $server_time - $a->{'timestamp'};
}
else {
$a->{'duration'} = &subs::time_abbrev_translator($settings->{'duration'});
}
}
$a->{'duration'} = abs $a->{'duration'};
if (($settings->{'s_display'} eq 'total') && ($a->{'total'} == 0 || $a->{'total'} == undef)) {
next;
}
if ($settings->{'s_visual'} eq 'historical' || $settings->{'s_visual'} eq '') {
foreach my $ts (@time_scopes) {
foreach my $scope (@time_lengths) {
my ($bt,$t1,$t2,$temp_timestamp);
($bt, $temp_timestamp) = &father_time({
scope => $scope,
ts => $ts,
lock => $settings->{'s_lock'},
timestamp => $timestamp
});
if ($a->{'timestamp'} > $bt && $a->{'timestamp'} < $temp_timestamp) {
if ($a->{'measures'} && $bmt == 0 ) {
foreach my $measure ( @{$a->{'measures'}} ) {
unless ($measure->{$settings->{'s_display'}} || $measure->{$settings->{'s_display'}} == 0) {
last;
}
foreach my $mk ( keys %{$measure} ) {
if ($measure->{'ts'} && $measure->{'ts'} ne '') {
$measure->{'timestamp'} = $measure->{'ts'};
delete $measure->{'ts'};
}
if (($measure->{'timestamp'} < $bt || $measure->{'timestamp'} > $temp_timestamp) && $settings->{'s_display'} eq $mk) {
unless (grep { $_->{'uuid'} eq $measure->{'uuid'} } @{$appts}) {
my $new_measure = {
app => $a->{'app'},
timestamp => $measure->{'timestamp'} || $measure->{'ts'},
type => 'measure',
uuid => $measure->{'uuid'},
measures => encode_json [ $measure ],
};
push @{$appts}, $new_measure;
next;
}
$measure = undef;
}
else {
if ($measure->{$mk} != undef || $measure->{$mk} == 0) {
$returner->{$ts}->{$scope}->{$mk . '_occurences'} += 1;
if ($settings->{'s_calc'} eq 'average' ) {
$returner->{$ts}->{$scope}->{'t_' . $mk} += $measure->{$mk};
my $sprinter = "%.2f";
if ($measure->{$mk} < 1 && $measure->{$mk} > -1) {
$sprinter = "%.4f";
}
$returner->{$ts}->{$scope}->{$mk} = sprintf($sprinter, $returner->{$ts}->{$scope}->{'t_' . $mk} / $returner->{$ts}->{$scope}->{$mk . '_occurences'}) if $measure->{$mk};
if ($returner->{$ts}->{$scope}->{$mk} == undef) {
$returner->{$ts}->{$scope}->{$mk} = 0;
}
}
elsif ($settings->{'s_calc'} eq 'high') {
$returner->{$ts}->{$scope}->{$mk} = $measure->{$mk} unless $returner->{$ts}->{$scope}->{$mk};
if ($measure->{$mk} > $returner->{$ts}->{$scope}->{$mk}) {
$returner->{$ts}->{$scope}->{$mk} = $measure->{$mk};
}
}
elsif ($settings->{'s_calc'} eq 'low') {
$returner->{$ts}->{$scope}->{$mk} = $measure->{$mk} unless $returner->{$ts}->{$scope}->{$mk};
if ($measure->{$mk} < $returner->{$ts}->{$scope}->{$mk}) {
$returner->{$ts}->{$scope}->{$mk} = $measure->{$mk};
}
}
else {
$returner->{$ts}->{$scope}->{$mk} += $measure->{$mk};# if $measure->{$mk} != undef;
}
$returner->{'total'}->{$scope}->{$mk} += 1;
}
}
}
}
}
elsif (grep { $_ eq $settings->{'s_display'} } keys %{$gb::budget_modes}) {
if ($settings->{'s_display'} eq 'quantity') {
if ($a->{'unit'} ne $settings->{'unit'}) {
my $neg = 0;
if ($a->{'quantity'} < 0) { $neg = 1; }
$a->{'quantity'} = abs $a->{'quantity'};
my ($formula,$evaluation,$uom,$format) = &formula_calculator($a->{'quantity'} . $a->{'unit'} . ' to ' . $settings->{'unit'});
$a->{'quantity'} = $evaluation unless $evaluation == 0;
$a->{'quantity'} = (abs $a->{'quantity'}) * -1 if $neg == 1;
$a->{'unit'} = $settings->{'unit'} unless $evaluation == 0;
}
}
if ($settings->{'s_calc'} eq 'average' ) {
$returner->{$ts}->{$scope}->{'t_' . $settings->{'s_display'}} += $a->{$settings->{'s_display'}};
$returner->{$ts}->{$scope}->{'c_' . $settings->{'s_display'}} += 1;
my $sprinter = "%.2f";
if ($a->{$settings->{'s_display'}} < 1 && $a->{$settings->{'s_display'}} > -1) {
$sprinter = "%.4f";
}
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = sprintf($sprinter, $returner->{$ts}->{$scope}->{'t_' . $settings->{'s_display'}} / $returner->{$ts}->{$scope}->{'c_' . $settings->{'s_display'}});
if ($returner->{$ts}->{$scope}->{$settings->{'s_display'}} == 0) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = 0;
}
}
elsif ($settings->{'s_calc'} eq 'high') {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = 0 unless $returner->{$ts}->{$scope}->{$settings->{'s_display'}};
if ($a->{$settings->{'s_display'}} > $returner->{$ts}->{$scope}->{$settings->{'s_display'}}) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}};
}
}
elsif ($settings->{'s_calc'} eq 'low') {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}} unless $returner->{$ts}->{$scope}->{$settings->{'s_display'}};
if ($a->{$settings->{'s_display'}} < $returner->{$ts}->{$scope}->{$settings->{'s_display'}}) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}};
}
}
else {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} += $a->{$settings->{'s_display'}} unless $settings->{'s_display'} eq 'occurences';
}
}
$returner->{$ts}->{$scope}->{'timestamp'} = $a->{'timestamp'};
$returner->{$ts}->{$scope}->{'occurences'} += 1;# unless $settings->{'s_display'} eq 'occurences';
$a->{'occurences'} = 1;
$returner->{$ts}->{$scope}->{'formatted_duration'} = &subs::duration_sayer((abs $returner->{$ts}->{$scope}->{'duration'}) / 1000);
# $returner->{$ts}->{$scope}->{'total'} += abs $a->{'total'} if $a->{'total'};
# $returner->{$ts}->{$scope}->{'amount'} += abs $a->{'amount'} if $a->{'amount'};
$returner->{'total'}->{$scope}->{$settings->{'s_display'}} += abs $a->{$settings->{'s_display'}};
$returner->{'count'}->{$scope}->{$settings->{'s_display'}} += 1;
$returner->{'average'}->{$scope}->{$settings->{'s_display'}} = sprintf("%.2f", $returner->{'total'}->{$scope}->{$settings->{'s_display'}} / $returner->{'count'}->{$scope}->{$settings->{'s_display'}});
if ($settings->{'budget'} && $settings->{'s_calc'} eq 'sum' && $returner->{$ts}->{$scope}->{$settings->{'s_display'}} != 0) {
unless ($returner->{'autocalc'}) {
$returner->{'autocalc'} = &subs::cache_get({ app => $returner->{'app'}, context => 'autocalc', subcontext => $settings->{'s_display'} });
}
my $budget = &budget_calculator({
app => $returner->{'app'},
budget => $settings->{'budget'},
circumstance => $settings->{'s_display'},
value => $returner->{$ts}->{$scope}->{$settings->{'s_display'}},
scope => $scope,
appts => $appts,
settings => $settings
});
if ($returner->{$ts}->{$scope}->{$settings->{'s_display'}} && $ts eq 'this' &&
&subs::timespan_widener($budget->{'scope_name'}) eq &subs::timespan_widener($scope) && $budget->{'is_scope'} eq 'yes' &&
$settings->{'s_display'} eq $budget->{'circumstance'}) {
$returner->{'cachable'} = $budget if $budget->{'colour'};
}
$returner->{$ts}->{$scope}->{'budget'} = $budget;
$returner->{'budgets'} = $budget->{'budgets'};
$returner->{'budget_status'}->{$scope}->{$settings->{'s_display'}}->{'expected'} += $budget->{'expected'};
$returner->{'budget_status'}->{$scope}->{$settings->{'s_display'}}->{'actual'} += $budget->{'actual'};
$returner->{'budget_status'}->{$scope}->{$settings->{'s_display'}} = &budget_status_maker($returner->{'budget_status'}->{$scope}->{$settings->{'s_display'}});
}
if ($settings->{'s_display'} eq 'occurences') {
$returner->{'average'}->{$scope}->{$settings->{'s_display'}} = sprintf("%.2f", $returner->{'total'}->{$scope}->{$settings->{'s_display'}} / scalar @time_scopes);
}
foreach my $d ( @display_options ) {
if ($returner->{$ts}->{$scope}->{$d->{'name'}} > $returner->{'highest'}->{$scope}->{$d->{'name'}}) {
$returner->{'highest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
elsif ($returner->{'highest'}->{$scope}->{$d->{'name'}} == undef) {
$returner->{'highest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
if ($returner->{$ts}->{$scope}->{$d->{'name'}} < $returner->{'lowest'}->{$scope}->{$d->{'name'}}) {
$returner->{'lowest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
elsif ($returner->{'lowest'}->{$scope}->{$d->{'name'}} == undef) {
$returner->{'lowest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
$returner->{$ts}->{$scope}->{'start_timestamp'} = $bt;
$returner->{$ts}->{$scope}->{'end_timestamp'} = $temp_timestamp;
}
}
}
}
}
elsif ($settings->{'s_visual'} eq 'allocation') {
my @localtime = localtime($a->{'timestamp'} / 1000);
if ($a->{'measures'}) {
foreach my $measure ( @{$a->{'measures'}} ) {
foreach my $mk ( keys %{$measure} ) {
unless ($measure->{$settings->{'s_display'}} || $measure->{$settings->{'s_display'}} == 0) {
last;
}
if (!$measure->{'uuid'}) {
$measure->{'uuid'} = &subs::random_string_creator(15);
}
if ($measure->{'ts'} && $measure->{'ts'} ne '') {
$measure->{'timestamp'} = $measure->{'ts'};
delete $measure->{'ts'};
}
if ($settings->{'s_display'} eq $mk) {
unless (grep { $_->{'uuid'} eq $measure->{'uuid'} } @{$appts}) {
my $new_measure = {
app => $a->{'app'},
timestamp => $measure->{'timestamp'} || $measure->{'ts'},
type => 'measure',
uuid => $measure->{'uuid'} || &subs::random_string_creator(8),
$mk => $measure->{$settings->{'s_display'}},
measures => encode_json [ $measure ],
};
push @{$appts}, $new_measure;
undef $a;
}
$measure = undef;
}
}
}
}
next unless $a->{'uuid'};
for (my $n = 0; $n <= scalar @time_lengths; $n++) {
if (($a->{$settings->{'s_display'}} || $a->{$settings->{'s_display'}} == 0) || ( $bmt > 0 )) {
my $scope = $time_lengths[$n];
my $ts = $localtime[$n];
if ($scope eq 'month') { $ts += 1; }
if ($scope eq 'year') { $ts += 1900; }
# if ($scope eq 'wday') { $ts += 1; }
$returner->{$ts}->{$scope}->{'occurences'} += 1;
if ($settings->{'s_calc'} eq 'average' ) {
$returner->{$ts}->{$scope}->{'t_' . $settings->{'s_display'}} += $a->{$settings->{'s_display'}};
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = sprintf("%.2f", $returner->{$ts}->{$scope}->{'t_' . $settings->{'s_display'}} / $returner->{$ts}->{$scope}->{'occurences'});
if ($returner->{$ts}->{$scope}->{$settings->{'s_display'}} == 0) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = 0;
}
}
elsif ($settings->{'s_calc'} eq 'high') {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}} unless $returner->{$ts}->{$scope}->{$settings->{'s_display'}};
if ($a->{$settings->{'s_display'}} > $returner->{$ts}->{$scope}->{$settings->{'s_display'}}) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}};
}
}
elsif ($settings->{'s_calc'} eq 'low') {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}} unless $returner->{$ts}->{$scope}->{$settings->{'s_display'}};
if ($a->{$settings->{'s_display'}} < $returner->{$ts}->{$scope}->{$settings->{'s_display'}}) {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} = $a->{$settings->{'s_display'}};
}
}
else {
$returner->{$ts}->{$scope}->{$settings->{'s_display'}} += $a->{$settings->{'s_display'}};
}
$returner->{$ts}->{$scope}->{'formatted_duration'} = &subs::duration_sayer((abs $returner->{$ts}->{$scope}->{'duration'}) / 1000);
$returner->{$ts}->{$scope}->{'total'} += $a->{'total'};
unless (grep { $settings->{'s_display'} eq $_ } keys %{$gb::budget_modes}) {
#$returner->{$ts}->{$scope}->{$settings->{'s_display'}} += $a->{$settings->{'s_display'}};
}
foreach my $d ( @display_options ) {
if ($returner->{$ts}->{$scope}->{$d->{'name'}} > $returner->{'highest'}->{$scope}->{$d->{'name'}}) {
$returner->{'highest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
elsif ($returner->{'highest'}->{$scope}->{$d->{'name'}} == undef) {
$returner->{'highest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
if ($returner->{$ts}->{$scope}->{$d->{'name'}} < $returner->{'lowest'}->{$scope}->{$d->{'name'}}) {
$returner->{'lowest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
elsif ($returner->{'lowest'}->{$scope}->{$d->{'name'}} == undef) {
$returner->{'lowest'}->{$scope}->{$d->{'name'}} = $returner->{$ts}->{$scope}->{$d->{'name'}};
}
}
}
}
}
if (abs $a->{'duration'} > abs $returner->{'longest'}->{'duration'}) {
$returner->{'longest'} = $a;
}
if (abs $a->{'duration'} < abs $returner->{'shortest'}->{'duration'}) {
$returner->{'shortest'} = $a;
}
my $between = $a->{'timestamp'} - $returner->{'last_seen'}->{'timestamp'};
if ($between > $returner->{'longest_between'}->{'duration'}) {
$returner->{'longest_between'} = clone $a;
$returner->{'longest_between'}->{'duration'} = $between;
}
if ($between < $returner->{'shortest_between'}->{'duration'} || $returner->{'shortest_between'}->{'duration'} == undef) {
$returner->{'shortest_between'} = clone $a;
$returner->{'shortest_between'}->{'duration'} = $between;
}
push @{$returner->{'betweens'}}, $between;
$returner->{'last_seen'} = $a;
if ($a->{'server_time'} > $returner->{'last_recorded'}->{'server_time'}) {
$returner->{'last_recorded'} = $a;
}
if ($a->{'server_time'} < $returner->{'first_recorded'}->{'server_time'} || $returner->{'first_recorded'}->{'server_time'} == undef) {
$returner->{'first_recorded'} = $a;
}
$returner->{'total_duration'} += abs $a->{'duration'};
$returner->{'total_occurences'} += 1;
}
$returner->{'average_duration'} = eval { $returner->{'total_duration'} / $returner->{'total_occurences'} } || undef;
foreach my $betweens ( @{$returner->{'betweens'}} ) {
$returner->{'between_total'} += $betweens;
}
$returner->{'between_average'} = eval { $returner->{'between_total'} / $returner->{'total_occurences'} } || undef;
}
foreach my $ts ( @time_scopes ) {
if ($returner->{$ts} == undef) {
@revised_time_scopes = grep { $_ ne $ts } @revised_time_scopes;
}
}
my @sb;
foreach my $s ( @display_options ) {
push @sb, $s->{'name'} unless grep { $_ eq $s->{'name'} } keys %{$gb::budget_modes};
}
my $jsb = encode_json \@sb;
@time_scopes = @revised_time_scopes;
push @time_scopes, qw/average total/;
if ($returner->{'budgets'}->{$settings->{'s_display'}}) {
&subs::cache_set({ app => $returner->{'app'}, context => 'budget', subcontext => $returner->{'cachable'}->{'circumstance'} },$returner->{'cachable'});
}
&Websocket::send('tab', $returner->{'sendable'});
&subs::appt_header_printer({ app => $returner->{'app'} });
undef $returner->{'sendable'};
undef $returner->{'cachable'};
$returner->{'evaluation'} = &subs::cache_get({ app => $app, context => 'evaluation' });
$returner->{'json_returner'} = encode_json $returner;
$returner->{'content'} = $c->render_to_string(
template => 'apps/inventory',
app => $app,
returner => $returner,
appts => $appts,
settings => $settings,
time_scopes => \@time_scopes,
time_lengths => \@time_lengths,
movements => $movements,
display_options => \@display_options,
evaluation => $returner->{'evaluation'}
);
return $returner;
}
sub father_time($data) {
my $start_time = &subs::rightNow();
my $scope = $data->{'scope'};
my $ts = $data->{'ts'};
my $lock = $data->{'lock'} || 'off';
my $timestamp = $data->{'timestamp'};
my ($bt,$temp_timestamp,$t1,$t2);
if ($gb::father_time->{$scope}->{$ts}->{$lock}->{'st'} > $start_time - 10000) {
$bt = $gb::father_time->{$scope}->{$ts}->{$lock}->{'bt'};
$temp_timestamp = $gb::father_time->{$scope}->{$ts}->{$lock}->{'tt'};
$gb::father_time->{$scope}->{$ts}->{$lock}->{'st'} = $start_time;
}
else {
if ($ts eq 'this') {
$temp_timestamp = $timestamp;
}
elsif ($ts =~ 'last') {
$temp_timestamp = &{$subs::time_subs->{$scope}}($timestamp);
if ($ts =~ /(^[0-9])/) {
my $tas = $ts;
$tas =~ s/last//gi;
my $tame = $gb::numerics->{$tas};
$tame = '' if $tas == 1;
$temp_timestamp = &{$subs::time_subs->{$tame . $scope}}($timestamp);
}
}
elsif ($ts =~ 'next') {
my $bt = &{$subs::time_subs->{$scope}}($timestamp);
my $t1 = $timestamp - $bt;
$temp_timestamp = $t1 + $timestamp;
if ($ts =~ /(^[0-9])/) {
my $tas = $ts;
$tas =~ s/next//gi;
my $tame = $gb::numerics->{$tas};
my $template_tame = 0;
if ($tas == 1) {
$tame = '';
}
else {
$template_tame = $timestamp - &{$subs::time_subs->{$scope}}($timestamp);
}
my $tamer = $timestamp - &{$subs::time_subs->{$tame . $scope}}($timestamp);
$temp_timestamp = $timestamp + $tamer + $template_tame;
}
}
if ($lock eq 'on' && grep { &subs::timespan_widener($scope) =~ /\Q$_/gi } qw/minute hour day week month year/) {
my $multiplier = $scope;
$multiplier =~ s/[^0-9.]//gi;
$multiplier = 1 unless $multiplier;
$scope =~ s/[^a-zA-Z]//gi;
$scope = lc $scope;
my @localtime = localtime $temp_timestamp / 1000;
if ($scope eq 'minute') {
my $second = localtime( $temp_timestamp / 1000 )->strftime( "%S");
$bt = &subs::ago_calc($second . 's', $temp_timestamp);
$temp_timestamp = &subs::ago_calc('-' . $multiplier . 'm',$bt);
}
elsif ($scope eq 'hour') {
my $hour = localtime( $temp_timestamp / 1000 )->strftime( "%H");
my $minute = localtime( $temp_timestamp / 1000 )->strftime( "%M");
my $second = localtime( $temp_timestamp / 1000 )->strftime( "%S");
$bt = &subs::ago_calc($minute . 'm ' . $second . 's', $temp_timestamp);
$temp_timestamp = &subs::ago_calc('-' . $multiplier . 'h', $bt);
}
elsif ($scope eq 'day') {
my $hour = localtime( $temp_timestamp / 1000 )->strftime( "%H");
my $minute = localtime( $temp_timestamp / 1000 )->strftime( "%M");
my $second = localtime( $temp_timestamp / 1000 )->strftime( "%S");
$bt = &subs::ago_calc( $hour . 'h ' . $minute . 'm ' . $second . 's',$temp_timestamp);
$temp_timestamp = &subs::ago_calc('-' . $multiplier . 'd', $bt);
}
elsif ($scope eq 'week') {
my $day = localtime( $temp_timestamp / 1000 )->strftime( "%d");
my $month = localtime( $temp_timestamp / 1000 )->strftime( "%m");
my $year = localtime( $temp_timestamp / 1000 )->strftime( "%Y");
my $wday = $localtime[6];
my $bwtemp = &subs::ago_calc($wday . 'd', $temp_timestamp);
my $awtemp = &subs::ago_calc('-' . ( 6 - $wday ) . 'd', $temp_timestamp);
$day = localtime( $bwtemp / 1000 )->strftime( "%d");
$month = localtime( $bwtemp / 1000 )->strftime( "%m");
$year = localtime( $bwtemp / 1000 )->strftime( "%Y");
$bt = &subs::ago_calc($month . '/' . $day . '/' . $year . ' 12am', $bwtemp);
$day = localtime( $awtemp / 1000 )->strftime( "%d");
$month = localtime( $awtemp / 1000 )->strftime( "%m");
$year = localtime( $awtemp / 1000 )->strftime( "%Y");
$temp_timestamp = &subs::ago_calc($month . '/' . $day . '/' . $year . ' 11:59:59pm', $awtemp);
}
elsif ($scope eq 'month') {
my $day = localtime( $temp_timestamp / 1000 )->strftime( "%d");
my $tday = localtime( $timestamp / 1000 )->strftime( "%d" );
my $year = localtime( $temp_timestamp / 1000 )->strftime( "%Y");
my $month = localtime( $temp_timestamp / 1000 )->strftime( "%m");
# $day = $tday - $day;
if ($ts =~ 'next') {
# $temp_timestamp = &subs::ago_calc($gb::months->[$month - 1]->{'days'} - $day . 'd', $temp_timestamp);
$day = localtime( $temp_timestamp / 1000 )->strftime( "%d");
if ($month == 12) {
# $month = 1;
}
else {
# $month--;
}
}
elsif ($ts =~ 'last') {
# $temp_timestamp = &subs::ago_calc($day + 1 . 'd', $temp_timestamp);
$day = localtime( $temp_timestamp / 1000 )->strftime( "%d");
$day = localtime( $temp_timestamp / 1000 )->strftime( "%d");
$month = localtime( $temp_timestamp / 1000 )->strftime( "%m");
$year = localtime( $temp_timestamp / 1000 )->strftime( "%Y");
}
my $last_day = $gb::months->[$month - 1]->{'days'};
my $datetime = $month . '/' . $last_day .'/' . $year . ' 11:59:59pm';
my $bdatetime = $month . '/1/' . $year . ' 12am';
$bt = &subs::ago_calc($bdatetime, $temp_timestamp);
$temp_timestamp = &subs::ago_calc($datetime, $temp_timestamp);
}
elsif ($scope eq 'year') {
my $year = localtime( $temp_timestamp / 1000 )->strftime( "%Y");
$bt = &subs::ago_calc('jan 1 ' . $year . ' 12am', $temp_timestamp);
$temp_timestamp = &subs::ago_calc('jan 1 ' . ($year + $multiplier) . ' 12am', $temp_timestamp);
}
}
else {
$bt = &{$subs::time_subs->{$scope}}($temp_timestamp); #timestamp at beginning
my $t1 = ($temp_timestamp - $bt);
$t2 = ($t1 + $temp_timestamp);
}
}
$gb::father_time->{$scope}->{$ts}->{$lock} = { bt => $bt, tt => $temp_timestamp, st => $start_time };
return ($bt,$temp_timestamp);
}
get '/manager/configure/appointment_list' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $results = &subs::db_query("select distinct app from settings where setting=? and value=?",'visible','checked');
my $appointments = $results->hashes;
foreach my $a (@{$appointments}) {
$a->{'app'} = &subs::unformat_name($a->{'app'});
$a->{'formatted_name'} = &subs::format_name($a->{'app'});
}
$c->render(
template => 'configure/appointment_lister',
appts => $appointments,
timestamp => &subs::rightNow()
);
};
get '/manager/configure/appointment_display' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $appts = &log_reader({ app => $app, view => 'appointment_display' });
my $config_window = $c->param('config');
my $preferred_appts = {};
my $measures = eval { return decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
foreach my $m ( keys %{$measures} ) {
}
$appts->{$app}->{'setting'}->{'measures'} = join ',', keys %{$measures};
$appts->{$app}->{'setting'}->{'app_measures'} = $measures;
my $packaging = eval { return decode_json $appts->{$app}->{'setting'}->{'packaging'} } || {};
$appts->{$app}->{'setting'}->{'app_packaging'} = $packaging;
$appts->{$app}->{'setting'}->{'packaging'} = join ',', map { $_ = $packaging->{$_}->{'name'} } keys %{$packaging};
my $home_plate = eval { return decode_json $appts->{$app}->{'setting'}->{'home_plate'} } || {};
$appts->{$app}->{'setting'}->{'app_home_plate'} = $home_plate;
$appts->{$app}->{'setting'}->{'home_plate'} = $home_plate->{'latitude'} . ' ' . $home_plate->{'longitude'};
foreach my $k (keys %{$appts}) {
if ($k =~ /^__/) {
next;
}
else {
$preferred_appts->{$k} = $appts->{$k}
}
}
$c->render(
template => 'configure/appointment_list',
appts => $preferred_appts,
'pos' => $gb::pos,
'abilities' => $gb::abilities,
config_window => $config_window,
timestamp => &subs::rightNow()
);
};
post '/manager/configure/permissions' => sub($c) {
my $timestamp = $c->param('timestamp');
my ($av_data);
if ($c->param('avData')) {
$av_data = decode_json($c->param('avData'));
}
my $constraints = $c->param('constraints');
foreach my $av (@{$av_data}) {
if ($av->{'kind'} eq 'audioinput') {
$av->{'icon'} = 'microphone';
}
elsif ($av->{'kind'} eq 'videoinput') {
$av->{'icon'} = 'monitor';
}
elsif ($av->{'kind'} eq 'audiooutput') {
$av->{'icon'} = 'speaker';
}
}
$c->render(json => { av_data => $av_data, constraints => $constraints });
};
get '/manager/configure' => sub($c) {
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
my $browser_tab = $c->param('browser_tab');
my $browser_tab_id = $c->param('browser_tab_id');
my $web_query = &subs::db_query('select * from websockets where browser_tab_id = ?',$browser_tab_id);
my $websockets = $web_query->hashes;
my $pseudonyms = &pseudonym_maker('config','');
my $content = $c->render_to_string(
template => 'configure/configure',
config => &subs::config_reader(),
device => $device,
websockets => $websockets,
pseudonyms => $pseudonyms,
);
my $contents = &window_maker({ user_agent => $c->param('user_agent'), app => 'configure', title => 'Configure', contents => $content },$timestamp);
$c->render(text => $contents);
};
post '/manager/configure' => sub ($c) {
my $app = $c->param('app');
# &subs::cache_delete({ app => $app });
my $setting = $c->param('setting');
my $value = $c->param('value');
my $timestamp = $c->param('timestamp');
my $source = $c->param('source');
if ($setting eq 'measures') {
$setting = 'app_measures';
my $measures = eval { decode_json &subs::setting_grabber({ app => $app, setting => 'app_measures' }) } || {};
my @potentials = split ',', $value;
foreach my $p ( @potentials ) {
unless ($measures->{$p}) {
$measures->{$p} = 0;
}
}
foreach my $m ( keys %{$measures} ) {
unless ( grep { $_ eq $m } @potentials ) {
delete $measures->{$m};
}
}
$value = encode_json $measures;
}
my $setting_data = { app => $app, setting => $setting, value => $value, timestamp => $timestamp, source => 'panel' };
&subs::setting_setter($setting_data);
undef @appointments;
my $appts = &log_reader({ app => $c->param('app'), view => 'appointment_display' });
my $measures = eval { decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
$appts->{$app}->{'setting'}->{'measures'} = join ',', keys %{$measures};
$appts->{$app}->{'setting'}->{'app_measures'} = $measures;
my $packaging = eval { decode_json $appts->{$app}->{'setting'}->{'packaging'} } || {};
$appts->{$app}->{'setting'}->{'app_packaging'} = $packaging;
$appts->{$app}->{'setting'}->{'packaging'} = join ',', map { $_ = $packaging->{$_}->{'name'} } keys %{$packaging};
my $home_plate = eval { return decode_json $appts->{$app}->{'setting'}->{'home_plate'} } || {};
$appts->{$app}->{'setting'}->{'app_home_plate'} = $home_plate;
$appts->{$app}->{'setting'}->{'home_plate'} = $home_plate->{'latitude'} . ' ' . $home_plate->{'longitude'};
if ($setting eq 'enc' && $value eq 'on') {
&subs::file_encrypter({ app => $app });
}
elsif ($setting eq 'enc' && $value eq 'off') {
&subs::file_decrypter({ app => $app });
}
my $preferred_appts = {};
foreach my $k (keys %{$appts}) {
if ($k =~ /^__/) {
next;
}
else {
$preferred_appts->{$k} = $appts->{$k}
}
}
if ($setting eq 'navigation') {
$value = &subs::time_abbrev_translator($value, $timestamp);
}
&Websocket::send($app, { console => '$(\'.appointment[app="' . $app . '"]\').attr(\'' . $setting . '\', \'' . $value . '\');' });
if ($source eq 'panel') {
my $window = ¢re_view_grabber({ c => $c, app => $c->param('app'), timestamp => $timestamp });
$c->render(text => $window);
}
else {
$c->render(
template => 'configure/appointment_list',
appts => $preferred_appts,
timestamp => &subs::rightNow()
);
}
};
get '/manager/configure/system_list' => sub($c) {
my $local_storage = eval { return decode_json $c->param('local_storage') } || {};
my $settings = { };
my ($db,$database,$sql) = &subs::database_grabber();
foreach my $dt ( @gb::device_types ) {
$settings->{$dt} = &subs::settings_grabber({ app => '__president', device => $dt });
}
my $stats = [];
my $tables = `sqlite3 $database .tables`;
foreach my $d ( sort split ' ', $tables ) {
my $results = &subs::db_query('select count(*) from ' . $d);
push @{$stats}, { formatted_table => &subs::format_name($d), table => $d, count => $results->hash->{'count(*)'} };
}
push @{$stats}, { formatted_table => 'Downloads', table => 'download', count => &subs::setting_grabber({ app => '__president', setting => 'download_count' }) || 0 };
my $evaluation = &subs::cache_get({ app => '__president', context => 'evaluation' }) || {};
$settings->{$device}->{'stats'} = $stats;
$c->render(template => '/configure/system_setting_list', stats => $stats, local_storage => $local_storage, evaluation => $evaluation, settings => $settings, last_restart => read_file($duty_file) );
};
post '/manager/configure/sys_setting' => sub($c) {
my $timestamp = $c->param('timestamp');
my $setting = &subs::unformat_name($c->param('setting'));
my $value = $c->param('value');
my $device = &subs::unformat_name($c->param('device'));
my $set = &subs::setting_setter({ app => '__president', setting => $setting, value => $value, device => $device });
$c->render(json => $set);
};
get '/manager/configure/restore_list' => sub($c) {
my @database = split '/', $c->session('database');
pop @database;
my $dir = join '/', @database;
$dir = $dir . '/';
$dir = &subs::home($c->param('president')) if $c->param('president');
my $returner = &subs::restore_list($dir);
@{$returner} = grep { $_->{'filename'} =~ /enc$/gi } @{$returner};
my @tables = qw/appointments settings notifications websites continent backups/;
$c->render(
template => 'configure/restore_list',
backups => $returner,
tables => \@tables
);
};
post '/manager/configure/new_database' => sub($c) {
my ($db,$database) = &subs::database_grabber();
&subs::db_query('VACUUM');
my $timestamp = $c->param('timestamp');
$c->param('reason' => 'new_database');
$c->render(text => $database) unless $c->param('credential');
my $president = $c->param('president');
$president = &subs::home($president);
my $old_db = $database;
my $download_location = &subs::home('~/.president');
my $temp_folder = &subs::home($download_location . '/' . &subs::random_string_creator(10)) . '/';
`mkdir -p $temp_folder` unless -e "$temp_folder";
my $database = $temp_folder . $president . '.db';
my $enc_file = $temp_folder . $president . '.enc';
my $secret = $c->param('credential');
my $credential = $c->session('suds');
my $misc_setting_list = &misc_setting_list();
my $server_time = &subs::rightNow();
`touch $database`;
my $schema_file = $temp_folder . 'schema.sql';
`sqlite3 $old_db .schema > $schema_file`;
my $command = `sqlite3 $database < $schema_file`;
`shred -u $schema_file`;
$sql = Mojo::SQLite->new('sqlite:' . $database);
$db = $sql->db;
my $secretive = &subs::encrypter($secret,$secret);
my $warranty = &subs::ago_calc(&subs::setting_grabber({ app => 'me', setting => 'warranty' }) || '-10d', $timestamp);
$db->insert('security', { level => 1, database => $database, timestamp => $timestamp, server_time => $server_time, credential => $secretive, uuid => &subs::random_string_creator(30) });
foreach my $set ( qw/misc/ ) {
my $settings = &subs::db_select('settings', undef, { app => $set })->hashes;
foreach my $s ( @{$settings} ) {
$db->insert('settings', $s);
}
}
my $backup = `sqlite3 $database ".backup '$database.1.db'"`;
my $encryption_standard = &subs::setting_grabber({ app => 'misc', setting => 'encryption_standard' } ) || "aes-256-ctr";
my $encrypt = `openssl enc -e -k "$secret" -$encryption_standard -pbkdf2 -in $database.1.db -out $enc_file`;
my $appendage = $universal_splitter . &subs::encrypter($secret,$encryption_standard);
`echo "$appendage" >> $enc_file`;
# my $devices = &subs::device_lister($timestamp);
# &subs::backup_now($c);
`shred -u $database`;
# `shred -u $database.1.db`;
`shred -u $database-shm`;
`shred -u $database-wal`;
my $new_enc_file = &subs::home($config->{'start_dir'}) . $president . '.enc';
`mv -v $enc_file $new_enc_file`;
# `rm -R $temp_folder`;
# $database = $old_db;
&subs::say_it('New Database ' . $c->param('president'));
$c->render(text => $database);
};
post '/manager/configure/restore_now' => sub($c) {
my $filename = $c->param('filename');
my $path = $filename;
$c->param('reason' => 'restore_database');
my ($db) = &subs::database_grabber();
my $credentials = &subs::db_select('security', ['level','credential'], { });
my $creds = $credentials->hashes;
@{$creds} = grep { $_->{'level'} ne 'padlock' } @{$creds};
@{$creds} = reverse @{$creds};
my $disposition->{'status'} = 'fail';
my $encryption_standard = &subs::setting_grabber({ app => 'misc', setting => 'encryption_standard' } ) || "aes-256-ctr";
foreach my $cred ( @{$creds} ) {
my $cr = &subs::decrypter($c->session('suds'),$cred->{'credential'});
if ($path =~ /enc$/gi) {
$filename =~ s/.enc$//gi;
my $t_database = $filename.'.db';
# my $scrypt = `printf "$cr" | scrypt dec -P $path $t_database`;
my $data = `tail $path`;
my @split_data = split $universal_splitter, $data;
$encryption_standard = &subs::decrypter($cr, $split_data[1]);
my $scrypt = `openssl enc -d -k "$cr" -$encryption_standard -pbkdf2 -in $path -out $t_database`;
if (-s $t_database > 5000) {
&subs::backup_now($c);
`shred -u $database`;
`shred -u $database-shm`;
`shred -u $database-wal`;
$database = $t_database;
$sql = Mojo::SQLite->new('sqlite:' . $database);
my $db = $sql->db;
my $secret = &subs::decrypter($cr,&subs::db_select('security', ['credential'], { level => 1 })->hash->{credential});
if (secure_compare $cr, $secret) {
$disposition->{'disposition'} = $database;
$c->session('suds' => $secret);
$c->session('database' => $database);
$disposition->{'status'} = 'succeed';
last;
}
else {
$c->session('authentication' => 'rejected');
}
}
}
}
$disposition = encode_json $disposition;
$c->render(text => $disposition);
};
get '/manager/configure/database_vacuum' => sub($c) {
my $timestamp = $c->param('timestamp');
my $html = "You are about to clean up settings from the following orphaned apps
";
my @unique_settings = &database_vacuum_bag();
foreach my $us ( @unique_settings ) {
$html .= '' . &subs::format_name($us) . "
";
}
$html .= '
';
$html = "Your house is clean!" if scalar @unique_settings == 0;
$html .= '
';
$c->render(json => { html => $html });
};
sub database_vacuum_bag() {
my @protection = @gb::protected;
push @protection, keys %{$gb::known_appts};
my $settings = &subs::db_query('select * from settings where setting !=?', 'uuid')->hashes;
foreach my $protect ( @protection ) {
@{$settings} = grep { $_->{'app'} ne $protect } @{$settings};
}
my $appts = &subs::db_query('select distinct(app) from appointments')->hashes;
my @unique_settings;
foreach my $s ( @{$settings} ) {
unless ( grep { $_->{'app'} eq $s->{'app'} } @{$appts} ) {
push @unique_settings, $s->{'app'} unless grep { $_ eq $s->{'app'} } @unique_settings;
}
}
return @unique_settings;
}
post '/manager/configure/database_vacuum_confirm' => sub($c) {
my $timestamp = $c->param('timestamp');
my $checkboxes = $c->param('checkboxes');
$checkboxes = eval { return decode_json $checkboxes } || [];
my $html = "You have cleaned:
";
foreach my $us ( @{$checkboxes} ) {
&subs::db_delete('settings', { app => $us });
$html .= &subs::format_name($us) . "
";
}
$html .= '
';
$c->render(json => { html => $html });
};
get '/manager/configure/database_doctor' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $returner = { tables => [], auuid => &subs::random_string_creator(20) };
my $tables = `sqlite3 $database .tables`;
@{$returner->{'tables'}} = split ' ', $tables;
$returner->{'html'} = 'You are about to perform surgery on ' . $database . '
This process is irreversible, unless you have backups or whatever!
';
foreach my $table ( @{$returner->{'tables'}} ) {
my $counter = &subs::db_query('select count(*) from ' . $table);
my $count = $counter->hash->{'count(*)'};
$returner->{'count'}->{$table} = $count;
my $existing = &subs::db_query('select * from ' . $table)->hashes;
my $delta = ($count - scalar @{$existing});
my $colour = 'black';
my $repairable = [];
if ($delta != 0) {
$colour = 'red';
#if ($existing->[-1]->{'app'}) {
my $repairs = &subs::db_query('select distinct(app) from ' . $table)->hashes;
if ($table eq 'settings') {
# push @{$repairs}, ({ app => 'me' }, { app => 'misc' }, { app => '__president' });
}
foreach my $a ( @{$repairs} ) {
my $ok = &subs::db_select($table, undef, { app => $a->{'app'} })->hashes;
push @{$repairable}, @{$ok};
# }
}
}
$returner->{'html'} .= ' ' . $table . ' Count: ' . $count . ' Shows: ' . scalar @{$existing} . ' Delta: ' . $delta;
if (scalar @{$repairable} > 0) {
$returner->{'html'} .= ' Repair: ' . scalar @{$repairable};
}
$returner->{'html'} .= '
';
}
$returner->{'html'} .= '
';
$c->render(json => $returner);
};
post '/manager/configure/database_doctor_confirm' => sub($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $auuid = $c->param('auuid') || &subs::random_string_creator(20);
my $returner = { tables => [], count => {} };
my $html = 'Now repairing ' . $database . '
';
&Websocket::send('server', { yellow => $html, uuid => $auuid });
my $download_location = &subs::home('~/.president');
my $temp_folder = &subs::home($download_location . '/' . &subs::random_string_creator(10));
`mkdir -p $temp_folder` unless -e "$temp_folder";
my $ndatabase = $temp_folder . '/' . &subs::random_string_creator(21) . '.db';
my $tdatabase = $temp_folder . '/' . &subs::random_string_creator(20) . '.db';
`touch $tdatabase`;
`touch $ndatabase`;
`sqlite3 $database .schema > $temp_folder/schema.sql`;
my $backup = `sqlite3 $database ".backup '$tdatabase'"`;
my $command = `sqlite3 $ndatabase < $temp_folder/schema.sql`;
my $nsql = Mojo::SQLite->new('sqlite:' . $ndatabase);
my $ndb = $nsql->db;
my $tsql = Mojo::SQLite->new('sqlite:' . $tdatabase);
my $tdb = $tsql->db;
my $tables = `sqlite3 $ndatabase .tables`;
@{$returner->{'tables'}} = split ' ', $tables;
foreach my $table ( @{$returner->{'tables'}} ) {
my $counter = $tdb->query('select count(*) from ' . $table);
my $count = $counter->hash->{'count(*)'};
$returner->{'count'}->{$table} = $count;
my $existing = $tdb->query('select * from ' . $table)->hashes;
if (scalar @{$existing} != $count) {
my $html = 'Now repairing ' . $count . ' ' . $table . '
';
&Websocket::send('server', { yellow => $html, uuid => $auuid });
my $repairable = [];
#if ($existing->[-1]->{'app'}) {
my $repairs = $tdb->query('select distinct(app) from ' . $table)->hashes;
foreach my $a ( @{$repairs} ) {
my $ok = $tdb->select($table, undef, { app => $a->{'app'} })->hashes;
foreach my $okay ( @{$ok} ) {
my $check = $tdb->select($table, $okay)->hashes;
if (scalar @{$check} == 0) {
eval { $ndb->insert($table, $okay) };
}
else {
}
}
push @{$repairable}, @{$ok};
}
#}
}
else {
my $html = 'Now inserting ' . $count . ' ' . $table . '
';
&Websocket::send('server', { yellow => $html, uuid => $auuid });
foreach my $i ( @{$tdb->select($table, undef, {})->hashes} ) {
$ndb->insert($table, $i);
}
}
}
$backup = `sqlite3 $ndatabase ".backup '$database'"`;
`shred -u $temp_folder/schema.sql`;
`shred -u $tdatabase`;
`shred -u $ndatabase`;
`rm -R $temp_folder`;
$c->render(json => $returner);
};
get '/manager/configure/vacuum_app' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $html = 'You are about to delete
' . &subs::format_name($app) . '
This process is irreversible, unless you have backups or whatever!
';
$c->render(text => $html );
};
post '/manager/configure/vacuum_app_confirm' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
&subs::vacuum_app($app);
&deletion_registration({ table => 'appointments', app => $app, scope => 'vacuum' });
my $html = '' . &subs::format_name($app) . ' is gone forever!
I hope you thought long and hard about it!
';
$c->render(text => $html );
};
post '/manager/configure/merge_database' => sub($c) {
my $filename = $c->param('filename');
my $action = $c->param('action');
Mojo::IOLoop->subprocess->run_p(sub {
my $configuration = {
file => $filename,
signatorial => &subs::signatorial_designer(),
misc_settings => &misc_setting_list()
};
my $disposition = &merge_database($c,$configuration);
my $temporary_file = $disposition->{'temporary_file'};
#`shred -u $temporary_file` if -e $temporary_file;
#`shred -u $temporary_file-shm` if -e $temporary_file;
#`shred -u $temporary_file-wal` if -e $temporary_file;
$disposition = encode_json $disposition;
});
my $disposition = { status => 'working' };
$c->render(json => $disposition);
};
sub merge_database($c,$configuration) {
my $filename = $configuration->{'file'};
my $remote_misc_settings = $configuration->{'misc_settings'};
my $misc_settings = &misc_setting_list();
my $deletions = eval { return decode_json $configuration->{'remote'}->{'deletions'} } || [];
my $port = $config->{'ssh_port'};
my $auuid = &subs::random_string_creator(10);
my $colour = $configuration->{'colour'};
my $html = 'Starting Merge ' . $filename . '
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
my ($db,$database) = &subs::database_grabber();
my $disposition->{'status'} = 'fail';
my $path = $filename;
my $download_location = &subs::home('~/.president');
my $temp_folder = &subs::home($download_location . '/' . &subs::random_string_creator(10));
`mkdir -p $temp_folder` unless -e "$temp_folder";
my $temporary_file = $temp_folder . '/tmpman.db';
my $credentials = &subs::db_query('select level,credential from security where level != ? order by server_time DESC', 'padlock');
my $signatorial = &subs::signatorial_designer();
my $last_update_time = &subs::db_select('backups', undef, { recipient => $signatorial, signatorial => $configuration->{'signatorial'} })->hashes->[-1];
$last_update_time = $last_update_time->{'server_time'} || 0;
$last_update_time = $configuration->{'gimme'} if $configuration->{'gimme'};
my $creds = $credentials->hashes;
@{$creds} = grep { $_->{'level'} ne 'padlock' } @{$creds};
@{$creds} = reverse @{$creds};
my $encryption_standard = &subs::setting_grabber({ app => 'misc', setting => 'encryption_standard' } ) || "aes-256-ctr";
my @updateables;
my @cache_bucket_updateables;
foreach my $cred ( @{$creds} ) {
my $crud = &subs::decrypter($c->session('suds'),$cred->{'credential'});
my $html = 'Testing Keys
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
if ($path =~ /enc$/gi) {
my $data = `tail $path`;
my @split_data = split $universal_splitter, $data;
next unless $data =~ /\Q$universal_splitter/gi;
$encryption_standard = &subs::decrypter($crud, $split_data[1]);
`openssl enc -d -k "$crud" -$encryption_standard -pbkdf2 -in $path -out $temporary_file`;
my $tsql = Mojo::SQLite->new('sqlite:' . $temporary_file);
if (-s $temporary_file > 5000 && eval { $tsql->db } && $tsql->dsn !~ /:$/) {
my $tdb = $tsql->db;
my $backups = &subs::db_query('select * from backups order by server_time DESC' )->hashes;
my $start_server_time = 0;
if ( scalar @{$backups} > 1 ) {
$start_server_time = $backups->[1]->{'server_time'};
}
my $html = 'Now merging
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
$disposition->{'temporary_file'} = $temporary_file;
my $stats = [];
my $tables = `sqlite3 $database .tables`;
my @u = sort split ' ', $tables;
my $count = 0;
my $universal_settings = {};
foreach my $q ( @u ) {
next if grep { $q eq $_ } @{$gb::forbidden->{'tables'}};
my $query;
if ($configuration->{'remote'}->{'manager'} ) {
$query = $tdb->query('select * from ' . $q . ' where server_time >= ?', $last_update_time);
}
else {
$query = $tdb->query('select * from ' . $q);
}
my $results = $query->hashes;
my $results_size = scalar @{$results};
if ($results_size > 0) {
my @resulters;
#&subs::say_it('Now merging ' . $results . ' ' .$q);
my $progress = $count / scalar @u * 100;
my $html = 'Now merging ' . scalar @{$results} . ' ' . $q . '
';
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
my $percentage = 0;
my $last_percent = 0;
my $last_alert = &subs::rightNow();
my $start_time = $last_alert;
for (my $n = 0; $n <= $results_size; $n++ ) {
my $r = $results->[$n];
my @resulters = @{&subs::db_select($q, undef, { uuid => $r->{'uuid'} })->hashes};
my $h = $resulters[0];
$percentage = sprintf("%.2f", $n / $results_size * 100);
if ($r->{'timestamp'}) {
if ($percentage >= $last_percent && $results_size > 1 && &subs::rightNow() >= ($last_alert + 250)) {
my $speed = abs sprintf("%.2f", $n / ($start_time - &subs::rightNow()) * 1000);
my $remaining = &subs::duration_sayer(((&subs::rightNow() - $start_time) / $percentage) * (100 - $percentage) / 1000);
my $html = '' . $n . ' / ' . scalar @{$results} . ' ' . &subs::format_name($q) . ' ' . $percentage . '% @ ' . $speed . '/sec ' . $remaining . '
' .
'';
$last_percent = $percentage;
$last_alert = &subs::rightNow();
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
}
if ($q eq 'settings') {
$universal_settings->{$r->{'app'}} = &subs::settings_grabber({ app => $r->{'app'}, device => $device, benign => 1 }) unless $universal_settings->{$r->{'app'}};
my $protected = 0;
foreach my $pr ( @gb::protected ) {
if ($r->{'app'} eq $pr) {
$protected = 1;
}
}
#next if $protected == 1;
unless ($universal_settings->{$r->{'app'}}->{'unique'} eq 'checked' || $protected == 1) {
push @cache_bucket_updateables, $r->{'app'} unless grep { $_ eq $r->{'app'} } @cache_bucket_updateables;
my $time_check = &subs::db_query('select * from settings where app=? and setting=? and subsetting = ? and server_time > ? and device = ?',
$r->{'app'}, $r->{'setting'}, $r->{'subsetting'}, $r->{'server_time'}, $device)->hashes;
unless (scalar @{$time_check} > 0) {
&subs::setting_setter({
app => $r->{'app'},
setting => $r->{'setting'},
value => $r->{'value'},
server_time => $r->{'server_time'},
uuid => &subs::random_string_creator(20),
device => $device,
subsetting => $r->{'subsetting'}
});
}
$universal_settings->{$r->{'app'}} = &subs::settings_grabber({ app => $r->{'app'}, device => $device });
next;
}
# push @cache_bucket_updateables, $r->{'app'} unless grep { $_ eq $r->{'app'} } @cache_bucket_updateables;
# &subs::setting_setter($r);
next;
}
if ($q eq 'security') {
if ($r->{'level'} == 1) {
my $sec_uuid = &subs::db_select('security', ['uuid'], { level => 1 })->hash->{uuid};
$r->{'level'} = 2 unless $sec_uuid eq $r->{'uuid'};
}
}
if ($configuration->{'remote'}->{'manager'} && $r->{'app'} && $r->{'file'} && $r->{'type'} ne 'snapshot' && $r->{'type'} ne 'backup' && $r->{'account'} ne 'gallery') {
my $files = eval { return decode_json $r->{'file'} } || [];
my $h_files = eval { return decode_json $h->{'file'} } || [];
if (eval { $files->{'f'} }) { $files = [ $files ]; }
if (eval { $h_files->{'f'} }) { $h_files = [ $h_files ]; }
if ($q eq 'appointments') {
$universal_settings->{$r->{'app'}}->{'enc'} = &subs::setting_grabber({ app => $r->{'app'}, device => $device, benign => 1 }) unless $universal_settings->{$r->{'app'}}->{'enc'};
if ($universal_settings->{$r->{'app'}}->{'enc'} eq 'on' && !$r->{'encryption_standard'} && $r->{'server_time'} > &subs::ago_calc('10m', &subs::rightNow()) && scalar @{$files} > 0) {
next;
}
}
if (scalar @resulters > 0) {
foreach my $home_file ( @{$h_files} ) {
if ($home_file->{'server_time'} <= $r->{'server_time'} ) {
unless ( grep { $home_file->{'uuid'} eq $_->{'uuid'} } @{$files}) {
# &delete_file({ app => $h->{'app'}, app_uuid => $h->{'uuid'}, file_uuid => $home_file->{'uuid'} });
push @{$files}, $home_file;
$r->{'server_time'} = &subs::rightNow();
}
}
else {
unless ( grep { $home_file->{'uuid'} eq $_->{'uuid'} } @{$files}) {
push @{$files}, $home_file;
}
}
}
}
my $file_count = 0;
foreach my $fi ( @{$files} ) {
$file_count++;
foreach my $file_type ( qw/f thumb/ ) {
next unless $fi->{$file_type};
my $file = $fi->{$file_type};
$last_percent = $percentage;
$percentage = sprintf("%.2f", ($n + ($file_count / scalar @{$files})) / $results_size * 100);
if ($percentage >= $last_percent && $results_size > 0 && &subs::rightNow() >= ($last_alert + 250)) {
my $speed = abs sprintf("%.2f", $n / ($start_time - &subs::rightNow()) * 1000);
my $remaining = &subs::duration_sayer(((&subs::rightNow() - $start_time) / $percentage) * (100 - $percentage) / 1000);
my $html = '' . sprintf("%.2f", ($n + ($file_count / scalar @{$files}))) . ' / ' . scalar @{$results} . ' ' . &subs::format_name($q) . ' ' . $percentage . '% @ ' . $speed . '/sec ' . $remaining .'
' .
'';
$last_percent = $percentage;
$last_alert = &subs::rightNow();
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
}
my ($destination,$asset,$type) = &subs::file_device_renamer({ file => $file, app => $r->{'app'}, misc_settings => $misc_settings, type => $fi->{'type'} });
$fi->{'type'} = $type unless $fi->{'type'};
my $dest = $destination . $asset;
if (my @h_fil = grep { $_->{'uuid'} eq $fi->{'uuid'} } @{$h_files} ) {
my $h_file = $h_fil[0];
my ($hdestination,$hasset) = &subs::file_device_renamer({ file => $h_file->{$file_type}, app => $h->{'app'}, misc_settings => $misc_settings, type => $h_file->{'type'} });
unless ($asset eq $hasset) {
if (-e $destination . $hasset) {
my $hassethoff = $destination . $hasset;
`shred -u $hassethoff`;
}
}
}
unless (-e $dest) {
`mkdir -p $destination`;
$destination = $destination . $asset;
if ($configuration->{'remote'}) {
#$file = url_unescape $file;
my $url = $configuration->{'remote'}->{'manager'} . '/file_open?timestamp=' . $r->{'server_time'} . '&as_is=yes&file=' . $file;
my $file_data = $configuration->{'remote'}->{'ua'}->get($url)->result;
if ($file_data) {
unless ($file_data->body eq 'not found') {
my $fd = $file_data->body;
$fd = decode_base64 $fd;
write_file($dest,$fd);
}
}
}
}
$file = $dest;
$fi->{$file_type} = $file;
}
}
$r->{'file'} = encode_json $files;
}
unless ( grep { $_->{'uuid'} eq $r->{'uuid'} && $_->{'table'} eq $q } @{$deletions} ) {
if (scalar @resulters == 0) {
eval { &subs::db_insert($q,$r)};
}
else {
eval { &subs::db_update($q,$r, { uuid => $r->{'uuid'} } ) } unless $h->{'server_time'} >= $r->{'server_time'};
}
if ($q eq 'appointments') {
push @updateables, { app => $r->{'app'}, uuid => $r->{'uuid'} } unless grep { $_->{'app'} eq $r->{'app'} } @updateables;
}
}
}
}
}
$disposition->{'disposition'} = $database;
$disposition->{'status'} = 'succeed';
my $known_backup = &subs::db_select('backups', undef, { uuid => $backups->[0]->{'uuid'} })->hashes;
if ($known_backup->[0]->{'reason'} =~ /remote/gi) {
my $defunct_backups = &subs::db_query('delete from backups where recipient=? and signatorial=? and destination=? and server_time < ? and uuid != ?',
$backups->[0]->{'recipient'}, $backups->[0]->{'signatorial'}, $backups->[0]->{'destination'}, $backups->[0]->{'server_time'}, $backups->[0]->{'uuid'});
$disposition->{'backup_uuid'} = $backups->[0]->{'uuid'};
}
}
last;
}
}
}
my $percentage = 0;
my $last_percent = 0;
my $last_alert = &subs::rightNow();
my $start_time = $last_alert;
my $results_size = scalar @updateables;
for (my $n = 0; $n <= scalar @updateables; $n++) {
my $u = $updateables[$n];
if ($u->{'app'}) {
&budget_runner($u->{'app'});
&Websocket::send($u->{'app'}, { console => 'appointmentDetailGrabber(\'' . $u->{'app'} . '\',\'' . $u->{'uuid'} .'\');' });
my $header = eval { &subs::appt_header_printer({ app => $u->{'app'} }) };
$percentage = sprintf("%.2f", $n / $results_size * 100);
if ($percentage >= $last_percent && $results_size > 1 && &subs::rightNow() >= ($last_alert + 250)) {
my $speed = abs sprintf("%.2f", $n / ($start_time - &subs::rightNow()) * 1000);
my $remaining = &subs::duration_sayer(((&subs::rightNow() - $start_time) / $percentage) * (100 - $percentage) / 1000);
my $html = '' . $n . ' / ' . scalar @updateables . ' ' . &subs::format_name('informations') . ' ' . $percentage . '% @ ' . $speed . '/sec ' . $remaining . '
' .
'';
$last_percent = $percentage;
$last_alert = &subs::rightNow();
&Websocket::send('tab', { yellow => $html, uuid => $auuid, colour => $colour });
}
}
}
&deletion_performer($configuration->{'remote'}->{'deletions'});
if ( scalar @cache_bucket_updateables > 0 ) {
my $buc = &subs::cache_get({ app => 'relational', context => 'buckets' });
my $bub = &subs::cache_get({ app => 'relational', context => 'bubbles' });
foreach my $cbd ( @cache_bucket_updateables ) {
delete $buc->{$cbd};
delete $bub->{$cbd};
}
&subs::cache_set({ app => 'relational', context => 'buckets' }, $buc);
&subs::cache_set({ app => 'relational', context => 'bubbles' }, $bub);
}
&Websocket::send('tab', { yellow => 'close', 'close' => 'yes', uuid => $auuid, colour => $colour });
&subs::say_it('fail') unless $disposition->{'status'} eq 'succeed';
`shred -u $temporary_file` if -e $temporary_file;
`shred -u $temporary_file-shm` if -e $temporary_file;
`shred -u $temporary_file-wal` if -e $temporary_file;
`rm -R $temp_folder`;
return $disposition;
}
get '/manager/budget' => sub($c) {
my $totals = {};
my $tally = {};
my $budgets = {};
my $new_settings = eval { return decode_json $c->param('new_settings') } || {};
foreach my $ns ( keys %{$new_settings} ) {
if ($new_settings->{$ns} =~ /[A-Za-z0-9.,-]/gi) {
if ($ns =~ /_time/gi) {
$new_settings->{$ns} = &subs::ago_calc($new_settings->{$ns}, &subs::rightNow());
}
&subs::setting_setter({ app => 'budget', setting => $ns, value => $new_settings->{$ns} });
}
else {
&subs::setting_deleter({ app => 'budget', setting => $ns });
}
}
my @dollas = qw/amount tax aux total/;
my @categories = qw/category subcategory/;
my $categories = { };
for (my $n = 1; $n <= 100; $n++) {
my $u = 'subcategory' . $n;
push @categories, $u;
# $categories->{$u} = {};
}
my $timestamp = $c->param('timestamp');
my $time_machine = $c->param('time_machine');
my $settings = &subs::settings_grabber({ app => 'budget' });
my $display = $c->param('display') || $settings->{'display'};
if ($settings->{$display . '_display'} ne '') {
my $d = eval { decode_json $settings->{$display . '_displays'} };
foreach my $k ( keys %{$d->{$settings->{$display . '_display'}}} ) {
$c->param($k, $d->{$settings->{$display . '_display'}}->{$k});
&subs::setting_setter({ app => 'budget', setting => $k, value => $d->{$settings->{$display . '_display'}}->{$k} });
}
$d->{$settings->{$display . '_display'}}->{$display . '_display'} = $settings->{$display . '_display'};
$settings = &subs::settings_grabber({ app => 'budget' });
}
my $display_categorization = $settings->{'display_categorization'};
my $scope = $settings->{'scope'} || 'hour';
my $movement = eval { decode_json $c->param('movement') || $settings->{'movement'} } || ['all'];
my $project = eval { decode_json $c->param('projects') || $settings->{'projects'} } || ['all'];
my $account = eval { decode_json $c->param('accounts') || $settings->{'accounts'} } || ['all'];
my $columns = eval { decode_json $c->param('columns') || $settings->{'columns'} } || ['all'];
my $timeshift = $c->param('timeshift');
my ($db,$database,$sql) = &subs::database_grabber();
my @columns = qw/app when occurences occurence_budget duration duration_budget duration_percent total_budget manufacturer item vendor account project amount tax aux total/;
my $tr = {};
my @time_scopes = ('next', 'this','last');
my @time_widths;
my @time_lengths = qw/minute hour day week month year/;
if ($settings->{'s_visual'} eq 'allocation') {
@time_scopes = undef;
for (my $n = 0; $n <= 366; $n++) {
push @time_scopes, $n;
}
@time_lengths = qw/second minute hour mday month year wday yday isdst/;
@time_widths = ( 60, 60, 24, 31, 12, 150, 7, 365, 2 );
}
else {
for (my $n = 2; $n <= 30; $n++) {
push @time_scopes, $n . 'last' if $n <= 10;
unshift @time_scopes, $n . 'next' if $n <= 10;
}
}
my ($bt,$t1,$t2);
if ($settings->{'start_time'} || $settings->{'end_time'}) {
$bt = $settings->{'start_time'};
$t2 = $settings->{'end_time'};
if ($settings->{'start_time'} && !$settings->{'end_time'}) {
$t2 = &subs::rightNow();
}
elsif (!$settings->{'start_time'} && $settings->{'end_time'}) {
$bt = &subs::rightNow();
}
}
else {
if ($time_machine) {
$timestamp = &subs::ago_calc($time_machine,$timestamp);
}
if ($timeshift) {
$timestamp = &subs::ago_calc($timeshift,$timestamp);
}
$bt = &{$subs::time_subs->{$scope}}($timestamp); #timestamp at beginning
$t1 = ($timestamp - $bt);
$t2 = ($timestamp);
($bt, $t2) = &father_time({
scope => $scope,
ts => $settings->{'time_when'},
lock => $settings->{'s_lock'},
timestamp => $timestamp
});
if ($settings->{'when_multiplier'}) {
my $tt = ($t2 - $bt) * $settings->{'when_multiplier'};
$bt = $t2 - $tt;
}
}
my $total_duration = $t2 - $bt;
my $last_inventory = $bt;
my $accountals = &subs::db_query('select distinct(app) from settings where setting=? and value=? order by app', 'pos', 'account');
my $accounts = $accountals->hashes;
push @{$accounts}, { app => 'gallery' };
unshift @{$accounts}, { app => 'all' };
my $all_accounts = $accounts;
unless (grep { $_ eq 'all' } @{$account}) {
my @acco;
foreach my $a ( @{$account} ) {
push @acco, grep { $_->{'app'} eq $a } @{$accounts};
}
$accounts = \@acco;
}
my $acc = {};
my $all_columns = \@columns;
if (grep { $_ eq 'all' } @{$columns}) {
$columns = $all_columns;
}
my $projections = &subs::db_query('select distinct(app) from settings where setting=? and value=? order by app', 'pos', 'project');
my $projects = $projections->hashes;
unshift @{$projects}, { app => 'all' };
my $all_projects = $projects;
unless (grep { $_ eq 'all' } @{$project}) {
my @proj;
foreach my $a ( @{$project} ) {
push @proj, grep { $_->{'app'} eq $a } @{$projects};
}
$projects = \@proj;
}
my $transactions;
foreach my $accounting ( @{$accounts}) {
next if $acc->{$accounting->{'app'}};
$accounting->{'balance'} = 0;
my $inventory = &subs::db_query('select * from appointments where app=? and type=? and movement=?', $accounting->{'app'}, 'transaction','inventory');
my $inv = $inventory->hashes;
foreach my $i ( @{$inv} ) {
if ($i->{'timestamp'} < $timestamp) {
$accounting->{'balance'} = $i->{'amount'};
$last_inventory = $i->{'timestamp'};
}
}
my $transactional;
if ($display eq 'invoices') {
$transactional = &subs::db_query('select * from appointments where timestamp >= ? and timestamp <= ? order by timestamp',
$last_inventory,$t2);
}
else {
$transactional = &subs::db_query('select * from appointments where account = ? and type != ? and timestamp >= ? and timestamp <= ? order by timestamp',
$accounting->{'app'}, 'inventory',$last_inventory,$t2);
}
push @{$transactions}, @{$transactional->hashes};
if (grep { $_ eq 'all' } @{$movement}) {
}
else {
my $transactionality = [];
foreach my $m ( @{$movement} ) {
push @{$transactionality}, grep { $_->{'type'} eq $m } @{$transactions};
}
$transactions = $transactionality;
}
$last_inventory = $bt;
$acc->{$accounting->{'app'}} = $accounting;
}
unless ( grep { $_ eq 'all' } @{$project} ) {
my $tp = [];
foreach my $tr ( @{$project} ) {
push @{$tp}, grep { $_->{'project'} eq $tr } @{$transactions};
}
$transactions = $tp;
}
foreach my $t ( @{$transactions} ) {
$tally->{$t->{'app'}} = {
income => [],
expense => [],
transfer => [],
totals => {},
settings => &subs::settings_grabber({ app => $t->{'app' } })
} unless $tally->{$t->{'app'}};
my $pushable = $display_categorization;
if ($display_categorization eq 'category') {
$pushable = $tally->{$t->{'app'}}->{'settings'}->{'category'};
if ($pushable eq '') {
$pushable = 'unknown';
}
}
elsif ($display_categorization eq undef || $display_categorization eq '') {
$pushable = $t->{'app'};
}
else {
$pushable = $t->{$display_categorization};
}
$tally->{$pushable} = {
income => [],
expense => [],
transfer => [],
totals => { },
settings => &subs::settings_grabber({ app => $pushable })
} unless $tally->{$pushable};
# $t->{'movement'} = 'expense' unless $t->{'movement'};
$acc->{$t->{'account'}}->{'balance'} = $acc->{$t->{'account'}}->{'balance'} + $t->{'total'};
if ($t->{'timestamp'} >= $bt && $t->{'timestamp'} <= $t2) {
foreach my $dolla (@dollas) {
for (my $ca = 0; $ca <= scalar @categories; $ca++) {
my $cat = $categories[$ca];
my $cath = $cat;
if ($tally->{$t->{'app'}}->{'settings'}->{$cat}) {
my $distinct = $tally->{$t->{'app'}}->{'settings'}->{$cat};
if (0 == 0) {
$cath = $distinct;
}
unless ($categories->{$cath}->{'info'}->{$distinct}) {
$categories->{$cath}->{'info'}->{$distinct} = &subs::settings_grabber({ app => $tally->{$t->{'app'}}->{'settings'}->{$cat} });
}
if ($ca > 1) {
$cath = $categories->{$cath}->{'info'}->{'subcategory' . $ca - 1};
}
elsif ($ca > 0) {
$cath = $categories->{$cath}->{'info'}->{'category'};
}
$categories->{$cath}->{$tally->{$t->{'app'}}->{'settings'}->{$cat}}->{'ca'} = $ca;
if ($dolla eq 'amount') {
push @{$categories->{$cath}->{$tally->{$t->{'app'}}->{'settings'}->{$cat}}->{'list'}}, $t;
}
$categories->{$cath}->{$tally->{$t->{'app'}}->{'settings'}->{$cat}}->{$dolla} += $t->{$dolla};
}
}
}
if ($t->{'movement'} eq 'income') {
$t->{'t'} = 'income';
$t->{'occurences'} = 1;
$t->{'duration'} = abs $t->{'duration'};
foreach my $dolla ( @dollas ) {
$t->{$dolla} = abs $t->{$dolla};
}
foreach my $col ( @columns ) {
$totals->{'income'}->{$col} += $t->{$col};
}
}
elsif ($t->{'movement'} eq 'transfer') {
$t->{'t'} = 'transfer';
$t->{'occurences'} = 1;
$t->{'duration'} = abs $t->{'duration'};
#unless (grep { $_->{'uuid'} eq $t->{'uuid'} } @{$tally->{$t->{'app'}}->{$t->{'movement'}}}) {
foreach my $col ( @columns ) {
$totals->{'transfer'}->{$col} += $t->{$col};
}
#}
}
elsif ($t->{'movement'} eq 'expense') {
$t->{'t'} = 'expense';
$t->{'movement'} = 'expense';
$t->{'occurences'} = 1;
$t->{'duration'} = (abs $t->{'duration'}) * -1;
foreach my $dolla ( @dollas ) {
$t->{$dolla} = (abs $t->{$dolla}) * -1;
}
foreach my $col ( @columns ) {
$totals->{'expense'}->{$col} += $t->{$col};
}
}
foreach my $col ( @columns ) {
$totals->{'total'}->{$col} += $t->{$col};
$tally->{$pushable}->{'totals'}->{$t->{'movement'}}->{$col} += $t->{$col};
}
push @{$tally->{$pushable}->{$t->{'movement'}}}, $t;
}
}
foreach my $d ( keys %{$gb::transaction_types} ) {
$totals->{$d}->{'duration_percent'} = abs &subs::percent_formatter(abs $totals->{$d}->{'duration'} / $total_duration);
$totals->{$d}->{'duration'} = &subs::duration_sayer(abs $totals->{$d}->{'duration'} / 1000);
}
foreach my $app ( keys %{$tally} ) {
foreach my $dr ( keys %{$gb::budget_modes} ) {
my $budget = &budget_calculator({
app => $app,
budget => $tally->{$app}->{'settings'}->{'budget'},
circumstance => $dr,
scope => $scope,
value => $tally->{$app}->{'totals'}->{$dr},
settings => $tally->{$app}->{'settings'}
});
$tally->{$app}->{'budget'}->{$dr} = $budget if $budget->{'eval'};
}
}
if ($display eq 'budgets') {
$settings->{'budget_displays'} = eval { return decode_json $settings->{'budget_displays'} } || {};
}
elsif ($display eq 'statement') {
$settings->{'statement_displays'} = eval { return decode_json $settings->{'statement_displays'} } || {};
}
elsif ($display eq 'daily_sheet') {
$settings->{'daily_sheet_displays'} = eval { return decode_json $settings->{'daily_sheet_displays'} } || {};
}
my $content = $c->render_to_string(
timestamp => $timestamp,
accounts => $acc,
categories => $categories,
all_accounts => $all_accounts,
account => $account,
tally => $tally,
transactions => $transactions,
budgets => $budgets,
all_projects => $all_projects,
projects => $projects,
project => $project,
totals => $totals,
template => 'budget',
time_machine => $time_machine,
scope => $scope,
movement => $movement,
timeshift => $timeshift,
display => $display,
start => $bt,
end => $t2,
total_duration => $total_duration,
settings => $settings,
all_columns => $all_columns,
columns => $columns,
dollas => \@dollas,
time_scopes => \@time_scopes,
time_lengths => \@time_lengths
);
my $contents = &window_maker({ user_agent => $c->param('user_agent'), app => 'budget', title => 'Budget', contents => $content },$timestamp);
$c->render(text => $contents );
};
post '/manager/budget/edit' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $circumstance = $c->param('circumstance');
my $value = $c->param('value');
my $existing_budgets = $value;
&subs::cache_delete({ app => $app, context => 'autocalc' });
foreach my $br ( keys %{$gb::budget_modes} ) {
my $budget = &budget_calculator({
app => $app,
circumstance => $br,
value => 1,
scope => 'hour',
budget => &subs::setting_grabber({ app => $app, setting => 'budget' })
});
if ($budget->{'circumstance'} && $budget->{'circumstance'} ne $circumstance) {
if ($existing_budgets) {
$existing_budgets = $existing_budgets . ',' . $budget->{'budget'};
}
else {
$existing_budgets = $budget->{'budget'};
}
}
}
&subs::setting_setter({ app => $app, setting => 'budget', value => $existing_budgets });
$c->render(json => { existing_budgets => $existing_budgets, new_budget => $value });
};
post '/manager/budget/display/save' => sub($c) {
my $name = &subs::unformat_name($c->param('name'));
my $timestamp = $c->param('timestamp');
my $data = eval { return decode_json $c->param('data') } || [];
my $type = $c->param('type') || 'statement';
if (scalar @{$data} == 0) {
$c->render(json => {});
}
my $settings = &subs::settings_grabber({ app => 'budget' });
my $display_settings = { start_time => $settings->{'start_time'}, end_time => $settings->{'end_time'} };
foreach my $s ( keys %{$settings} ) {
if (my @ds = grep { $_ eq $s } @{$data}) {
$display_settings->{$s} = $settings->{$s};
}
}
my $returner = { data => $data, config => $display_settings };
my $cd = eval { return decode_json $settings->{$type . '_displays'} } || {};
$cd->{$name} = $display_settings;
my $jcd = encode_json $cd;
&subs::setting_setter({ app => 'budget', setting => $type . '_displays', value => $jcd });
$c->render(json => $returner);
};
post '/manager/budget/display/delete' => sub($c) {
my $name = &subs::unformat_name($c->param('name'));
my $display = $c->param('display');
my $sd = eval { return decode_json &subs::setting_grabber({ app => 'budget', setting => $display . '_displays' }) } || {};
if ($sd->{$name}) {
$sd->{$name} = undef;
}
my $jsd = encode_json $sd;
&subs::setting_setter({ app => 'budget', setting => $display . '_displays', value => $jsd });
$c->render(json => $sd);
};
get '/manager/budget/current_information' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $circumstance = $c->param('circumstance');
my $ci = &budget_current_information($app,$circumstance,$timestamp);
$c->render(text => $ci->{'template'});
};
sub budget_current_information($app,$circumstance,$timestamp) {
my $autocalc = &subs::cache_get({ app => $app, context => 'autocalc', subcontext => $circumstance });
my $budget = &subs::cache_get({ app => $app, context => 'budget', subcontext => $circumstance });
unless ($autocalc->{$budget}) {
$autocalc = &Manager::budget_autocalc({
app => $app,
circumstance => $circumstance,
});
}
my $ov = sprintf("%.5f", $autocalc->{$budget->{'scope_name'}}->{'result'} - $budget->{'budgeted'});
my $improvement = {
difference => $budget->{'value'} - $budget->{'budgeted'},
overall => eval { &{$gb::budget_modes->{$circumstance}->{'formatted'}}($ov) } || $ov,
percentage => eval { return &subs::percent_formatter(($budget->{'value'} - $budget->{'budgeted'}) / $autocalc->{$budget->{'scope_name'}}->{'result'}) } || 0,
overall_percentage => eval { return &subs::percent_formatter(($autocalc->{$budget->{'scope_name'}}->{'result'} - $budget->{'budgeted'}) / $autocalc->{$budget->{'scope_name'}}->{'result'})} || 0
};
my $c = app->build_controller;
my $template = $c->render_to_string(
template => 'apps/budget_current_information',
circumstance => $circumstance,
improvement => $improvement,
budget => $budget,
autocalc => $autocalc
);
return { template => $template, circumstance => $circumstance, improvement => $improvement, autocalc => $autocalc, budget => $budget };
}
sub budget_runner($app) {
# Mojo::IOLoop->subprocess->run_p(sub {
my ($db) = &subs::database_grabber();
my $scope;
my $timestamp = &subs::rightNow();
my $budgets = &subs::db_query('select distinct(app) as app,* from settings where app=? and setting = ? and device = ? and value is not null',$app,'budget', $device)->hashes;
my $sb = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'special_budgets' }) } || [];
my @budget_modes = ( @{$sb}, %{$gb::budget_modes} );
foreach my $b ( @{$budgets} ) {
my $app = $b->{'app'};
my @buds = split /,/, $b->{'value'};
foreach my $circumstance ( keys %{$gb::budget_modes} ) {
my $cache_budget = &subs::cache_get({ app => $app, context => 'budget', subcontext => $circumstance });
if ($cache_budget->{'scope'}) {
$scope = $cache_budget->{'scope'};
}
foreach my $bud ( @buds ) {
my @bt = split '/', $bud;
$scope = $bt[-1];
my $budget = &Manager::budget_calculator({
app => $app,
circumstance => $circumstance,
scope => $scope,
budget => $bud
});
if ($budget->{'is_scope'} && $circumstance eq $budget->{'circumstance'}) {
&subs::cache_delete({ app => $app, context => 'template' });
&subs::cache_set({ app => $app, context => 'budget', subcontext => $circumstance }, $budget);
my $msg = {
app => $app,
type => 'budget',
budget => {
colour => $budget->{'colour'},
circumstance => $budget->{'circumstance'},
}
};
&Websocket::send('tab', $msg);
my $ci = &budget_current_information($app,$circumstance,$timestamp);
&Websocket::send('tab', {
type => 'html',
content => $ci->{'template'},
selector => '.budget_current_information[app="' . $app .'"][circumstance="' . $circumstance . '"]'
});
}
}
}
}
my $header = &subs::appt_header_printer({ app => $app, timestamp => $timestamp });
# });
}
sub budget_calculator($data) {
my $app = $data->{'app'};
my $circumstance = $data->{'circumstance'};
my $value = $data->{'value'};
my $scope = $data->{'scope'};
my $settings = $data->{'settings'} || &subs::settings_grabber({ app => $app });
my $timestamp = $data->{'timestamp'} || &subs::rightNow();
my $returner = { app => $app, scope_name => &subs::timespan_widener($scope), value => $value };
my $budget = $data->{'budget'};
my $server_time = &subs::rightNow();
$budget = $data->{'budget'} || &subs::setting_grabber({ 'app' => $app, setting => 'budget' }) unless $data->{'budget'} =~ /[0-9]/gi;
my @budgets = split ',', $budget;
foreach my $b ( @budgets ) {
$returner->{'budget'} = $b;
my @bud = split '/', $b;
next unless $bud[-1];
$bud[-1] = 1 . $bud[-1] unless $bud[-1] =~ /[0-9]/;
$returner->{'scope_name'} = &subs::timespan_widener($bud[-1]);
$returner->{'duration'} = &subs::time_abbrev_translator($bud[-1],&subs::rightNow());
unless ($scope) {
$returner->{'scope'} = $returner->{'duration'} ;
}
else {
$returner->{'scope'} = &subs::time_abbrev_translator($bud[-1]);
$returner->{'duration'} = $returner->{'scope'} unless $value;
}
unless ($value) {
my ($db) = &subs::database_grabber();
my $appts = $data->{'appts'};
unless ($data->{'appts'}) {
my $ft_data = {
scope => $returner->{'scope_name'},
ts => 'this',
lock => $settings->{'s_lock'},
timestamp => $timestamp
};
my ($bt, $temp_timestamp) = &father_time($ft_data);
my @params = ( $app, $temp_timestamp, $bt );
my $query = 'select * from appointments where app = ? and timestamp <= ? and timestamp >= ? ';
if ($settings->{'s_movement'}) {
my $bail = 0;
unless ($settings->{'sss_movement'}) {
$settings->{'sss_movement'} = eval { return decode_json $settings->{'s_movement'} } || [];
}
$bail = 1 if grep { $_ eq 'all' } @{$settings->{'sss_movement'}};
if ($bail == 0) {
if (scalar @{$settings->{'sss_movement'}} > 0 ) { $query .= 'and ( '; }
foreach my $sm ( @{$settings->{'sss_movement'}} ) {
$query .= 'type = ? ' if scalar @params == 3;
$query .= ' or type = ? ' if scalar @params > 3;
push @params, $sm;
}
if (scalar @{$settings->{'sss_movement'}} > 0 ) { $query .= ' ) '; }
}
}
$query .= ' order by timestamp DESC';
$appts = &subs::db_query($query, @params)->hashes;
$data->{'appts'} = $appts;
}
foreach my $appt ( @{$appts} ) {
if ($circumstance eq 'duration') {
if ($appt->{'type'} eq 'start' || $appt->{'type'} eq 'record') {
$appt->{'duration'} = $server_time - $appt->{'timestamp'};
}
$value += abs $appt->{'duration'};;
}
elsif ($circumstance eq 'occurences') {
$value += 1;
}
elsif ($circumstance eq 'total') {
$value += (abs $appt->{'total'} || 0) if $value;
}
else {
# $value = 0 unless $value;
# $appt->{'measures'} = eval { return decode_json $appt->{'measures'} };
# next if scalar @{$appt->{'measures'}} == 0;
# $value += 0 if scalar @{$appt->{'measures'}} == 0;
# foreach my $m ( @{$appt->{'measures'}} ) {
# $value += $m->{$circumstance};
# }
}
}
$value = 0 if scalar @{$appts} == 0;
$returner->{'value'} = $value;
}
if ($bud[0] =~ /^\$/gi) {
my $bu = $bud[0];
$bu =~ s/\$//gi;
$returner->{'budgets'}->{'total'} = $b;
if ($circumstance eq 'total') {
$returner->{'circumstance'} = 'total';
$returner->{'budgeted'} = abs $bu;
$returner->{'formatted_value'} = abs $value;
last;
}
}
elsif ($bud[0] =~ /[a-zA-Z]/gi) {
if ($circumstance eq 'duration') {
$returner->{'budgets'}->{'duration'} = $b;
$returner->{'circumstance'} = 'duration';
$bud[0] = 1 . $bud[0] unless $bud[0] =~ /[0-9]/;
$returner->{'budgeted'} = &subs::time_abbrev_translator($bud[0],&subs::rightNow());
if ($value != 0) {
$returner->{'formatted_value'} = &subs::duration_sayer($value / 1000);
}
else {
$returner->{'formatted_value'} = 0;
}
last;
}
elsif ( (scalar grep { $circumstance eq $_ } keys %{$gb::budget_modes}) == 0 ) {
$returner->{'budget_name'} = $bud[0];
$returner->{'budget_name'} =~ s/[0-9.]//gi;
next unless $returner->{'budget_name'} eq $circumstance;
$returner->{'budgeted'} = $bud[0];
$returner->{'budgets'}->{$circumstance} = $b;
$returner->{'circumstance'} = $circumstance;
$returner->{'budgeted'} =~ s/[^0-9.]//gi;
$returner->{'formatted_value'} = $value;
last;
}
}
else {
$returner->{'budgets'}->{'occurences'} = $b;
if ($circumstance eq 'occurences') {
$returner->{'circumstance'} = 'occurences';
$returner->{'budgeted'} = $bud[0];
$returner->{'formatted_value'} = abs $value;
last;
}
}
}
if ($returner->{'budget'} && $returner->{'budgeted'}) {
if ($returner->{'duration'} eq $returner->{'scope'} && $returner->{'circumstance'} eq $circumstance) {
$returner->{'is_scope'} = 'yes';
}
$returner->{'expected'} = sprintf("%.19f",$returner->{'budgeted'} / $returner->{'duration'});
$returner->{'formatted_budgeted'} = sprintf("%.3f", $returner->{'expected'} * $returner->{'scope'}) . '/' . $returner->{'scope_name'};
$returner->{'formatted_budgeted'} = &subs::duration_sayer($returner->{'expected'} * $returner->{'duration'} / 1000) . '/' . $returner->{'scope_name'} if $circumstance eq 'duration';
$returner->{'actual'} = sprintf("%.19f", $returner->{'value'} / $returner->{'scope'});
$returner->{'threshold'} = $returner->{'expected'} * $returner->{'scope'};
$returner->{'eval'} = $returner->{'actual'} - $returner->{'expected'};
$returner->{'timestamp'} = $timestamp;
if ($scope ne $returner->{'scope_name'} && $returner->{'circumstance'} eq $circumstance) {
$returner->{'is_scope'} = 'no';
my $scoped = $returner->{'scope'} / &subs::time_abbrev_translator(1 . $scope ,&subs::rightNow());
$returner->{'expected'} = $returner->{'expected'} * $scoped;
$returner->{'actual'} = $returner->{'actual'} * $scoped;
$returner->{'expected'} = sprintf("%.19f",$returner->{'budgeted'} / ( $returner->{'duration'} * $scoped));
$returner->{'actual'} = sprintf("%.19f", ($returner->{'value'} * $scoped) / ($returner->{'scope'} * $scoped));
}
$returner = &budget_status_maker($returner);
}
else {
# $returner = {};
}
return $returner;
}
sub budget_status_maker($returner) {
my $status;
if ($returner->{'actual'} <= $returner->{'expected'} - ( $returner->{'expected'} * .0000000001) && $returner->{'actual'} >= $returner->{'expected'} - ($returner->{'expected'} * .2)) {
$status = 'budgeted';
$returner->{'synth'} = 'play -v .3 "| sox -n -p synth .51 sine 391 && play | sox -n -p synth .51 triangle 500"';
}
elsif ($returner->{'actual'} >= $returner->{'expected'} * 2) {
$status = 'abused';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .51 pinknoise 1125 && play | sox -n -p synth .51 whitenoise 100"';
}
elsif ($returner->{'actual'} >= $returner->{'expected'} * 1.2) {
$status = 'burnt_out';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .51 square 125 && play | sox -n -p synth .51 square 100"';
}
elsif ($returner->{'actual'} >= $returner->{'expected'}) {
$status = 'accomplished';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .26 pluck 329.64 && play | sox -n -p synth .26 pluck 391.99 && play | sox -n -p synth .26 pluck 369.99 && play | sox -n -p synth .26 pluck 293.672"';
}
elsif ($returner->{'actual'} <= $returner->{'expected'} / 4) {
$status = 'abandoned';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .51 triangle 261.64 && play | sox -n -p synth .51 triangle 261.64"';
}
elsif ($returner->{'actual'} <= $returner->{'expected'} / 2) {
$status = 'neglected';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .26 saw 349.23 && play | sox -n -p synth .26 saw 329.63 && play | sox -n -p synth .26 saw 415.3 && play | sox -n -p synth .26 saw 439.99"';
}
elsif ($returner->{'actual'} <= $returner->{'expected'}) {
$status = 'achievable';
$returner->{'synth'} = 'play -v .15 "| sox -n -p synth .26 pluck 293.67 && play | sox -n -p synth .26 pluck 349.23 && play | sox -n -p synth .26 pluck 349.23 && play | sox -n -p synth .26 pluck 311.13"';
}
$returner = &{$gb::budget_statuses->{$status}->{'notifier'}}($returner);
return $returner;
}
get '/manager/budget/autocalc' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $circumstance = $c->param('circumstance');
&subs::cache_delete({ app => $app, context => 'autocalc', subcontext => $circumstance });
&subs::cache_delete({ app => $app, context => 'budget', subcontext => $circumstance });
my $returner = &budget_autocalc({
app => $app,
circumstance => $circumstance,
});
$c->render(json => $returner );
};
sub budget_autocalc($data) {
my $app = $data->{'app'};
my $scope = $data->{'scope'};
my $circumstance = $data->{'circumstance'};
my $timestamp = $data->{'timestamp'};
my $server_time = &subs::rightNow();
if (my $cache = &subs::cache_get({ app => $app, context => 'autocalc', subcontext => $circumstance })) {
return $cache;
}
my $returner = {
minute => { symbol => 'm' },
hour => { symbol => 'h' },
day => { symbol => 'd' },
week => { symbol => 'w' },
month => { symbol => 'M' },
year => { symbol => 'y' },
};
my ($db) = &subs::database_grabber();
my $settings = &subs::settings_grabber({ app => $app });
my $appts = $data->{'appts'} || &subs::db_query('select * from appointments where app = ? order by server_time DESC LIMIT 1000', $app)->hashes;
if ($scope && $timestamp) {
my $duration = &subs::time_abbrev_translator(1 . $scope, $server_time);
my $beginning = $server_time - ( $duration * ($settings->{'s_scope_count'} || 1) );
@{$appts} = grep { $_->{'timestamp'} > $beginning } @{$appts};
# @{$appts} = grep { $_->{'timestamp'} >= $timestamp - $duration && $_->{'timestamp'} <= $timestamp + $duration } @{$appts};
my $new_returner = {};
foreach my $re ( keys %{$returner} ) {
$new_returner->{$re} = $returner->{$re} if $re eq $scope;
}
# $returner = $new_returner;
}
foreach my $r ( keys %{$returner} ) {
$returner->{$r}->{'duration'} = &subs::time_abbrev_translator(1 . $returner->{$r}->{'symbol'}, $server_time);
$returner->{$r}->{'close'} = [];
}
$returner->{'data'} = {};
foreach my $appt ( @{$appts} ) {
foreach my $r ( keys %{$returner} ) {
my @close = grep { $appt->{'timestamp'} + ($returner->{$r}->{'duration'} / 2) >= $_->{'timestamp'}
&& $appt->{'timestamp'} - ($returner->{$r}->{'duration'} / 2) <= $_->{'timestamp'} } @{$appts};
if ($circumstance eq 'occurences') {
push @{$returner->{$r}->{'close'}}, scalar @close;
}
elsif ($circumstance eq 'duration') {
my $total = 0;
foreach my $cl (@close) {
$total += abs $cl->{'duration'};
}
push @{$returner->{$r}->{'close'}}, $total;
}
elsif ($circumstance eq 'total') {
my $total = 0;
foreach my $cl (@close) {
$total += $cl->{'total'};
}
push @{$returner->{$r}->{'close'}}, $total;
}
else {
next unless $appt->{'measures'};
unless ($appt->{'measured'}) {
$appt->{'measures'} = eval { return decode_json $appt->{'measures'} } || [];
$appt->{'measured'} = 'yes';
}
my $total = 0;
foreach my $cl (@close) {
next unless $cl->{'measures'};
unless ($cl->{'measured'}) {
$cl->{'measures'} = eval { return decode_json $cl->{'measures'} } || [];
$cl->{'measured'} = 'yes';
}
foreach my $m ( @{$cl->{'measures'}} ) {
if ($m->{$circumstance}) {
$total += $m->{$circumstance};
}
}
}
push @{$returner->{$r}->{'close'}}, $total;
}
}
}
foreach my $r ( keys %{$returner} ) {
my $total = 0;
foreach my $close ( @{$returner->{$r}->{'close'}} ) {
$total += $close;
}
if ($circumstance eq 'occurences') {
$returner->{$r}->{'result'} = ($total / scalar @{$returner->{$r}->{'close'}});
$returner->{$r}->{'formatted_result'} = sprintf("%.3f", $returner->{$r}->{'result'}) . '/' . $r if $circumstance eq 'occurences';
}
elsif ($circumstance eq 'total') {
$returner->{$r}->{'result'} =~ /^([-])/gi;
$returner->{$r}->{'formatted_result'} = &subs::price_formatter( $returner->{$r}->{'result'}) . '/' . $returner->{$r}->{'symbol'};
}
elsif ($circumstance eq 'duration') {
$returner->{$r}->{'result'} = ($total / scalar @{$returner->{$r}->{'close'}});
$returner->{$r}->{'formatted_result'} = &subs::duration_sayer($returner->{$r}->{'result'} / 1000) . '/' . $r;
}
else {
$returner->{$r}->{'result'} = ($total / scalar @{$returner->{$r}->{'close'}});
$returner->{$r}->{'formatted_result'} = sprintf("%.3f", $returner->{$r}->{'result'}) . $circumstance . '/' . $r;
}
undef $returner->{$r}->{'close'};
}
$returner->{'data'}->{'circumstance'} = $circumstance;
$returner->{'data'}->{'app'} = $app;
$returner->{'data'}->{'formatted_app'} = &subs::format_name($app);
$returner->{'data'}->{'timestamp'} = &subs::rightNow();
&subs::cache_set({app => $app, context => 'autocalc', subcontext => $circumstance }, $returner);
return $returner;
}
get '/manager/notifications/list' => sub($c) {
my $content = ¬ification_grabber({});
my $contents = &window_maker({ user_agent => $c->param('user_agent'), app => 'notifications', title => 'Notifications', contents => $content },$c->param('timestamp'));
$c->render(text => $contents);
};
sub notification_grabber($data) {
my $timestamp = &subs::rightNow();
my @notifications;
my $settings = &subs::settings_grabber({ app => 'notifications', benign => 1 });
my $notifications = { titles => [], apps => [], settings => $settings };
my ($db,$database,$sql) = &subs::database_grabber();
my $q = &subs::db_query('select * from notifications order by timestamp DESC LIMIT 100');
my $more_notifications = $q->hashes;
if ($device eq 'mobile') {
my $nl = `termux-notification-list`;
my $notifications = decode_json($nl);
foreach my $n ( @{$notifications} ) {
if ($n->{'title'} && !grep { $_->{'id'} eq $n->{'id'} } @{$more_notifications}) {
my $ts = &subs::ago_calc($n->{'when'},$timestamp);
&subs::db_insert('notifications', {
id => $n->{'id'},
app => &subs::unformat_name($n->{'title'}),
timestamp => $ts,
tag => $n->{'tag'},
message => $n->{'content'},
title => $n->{'title'},
key => $n->{'key'},
image => "/images/make believe/face.png",
uuid => &subs::random_string_creator(20)
});
}
}
}
$q = &subs::db_query('select * from notifications order by timestamp DESC');
$more_notifications = $q->hashes;
foreach my $m ( @{$more_notifications}) {
push @{$notifications->{'apps'}}, $m->{'app'} unless grep { $m->{'app'} eq $_ } @{$notifications->{'apps'}};
}
if ($settings->{'filter'} && $settings->{'filter'} ne '' && $settings->{'filter'} ne 'all') {
@{$more_notifications} = grep { $_->{'app'} eq $settings->{'filter'} } @{$more_notifications};
}
if ($settings->{'search'} && $settings->{'search'} ne '') {
my $search = $settings->{'search'};
@{$more_notifications} = grep { $_->{'app'} =~ /\Q$search/gi || $_->{'message'} =~ /\Q$search/gi } @{$more_notifications};
}
if ($data->{'scroll'} eq 'down') {
my @now_notifications = splice @{$more_notifications}, $data->{'position'} * 100;
@{$more_notifications} = @now_notifications;
}
unless ($data->{'delete'}) {
splice @{$more_notifications}, 100;
}
my $content;
my $c = app->build_controller;
foreach my $m ( @{$more_notifications}) {
$notifications->{'content'} .= $c->render_to_string(
n => $m,
template => 'notification',
);
}
$notifications->{'list'} = $more_notifications;
return $notifications;
}
post '/manager/notifications/remove' => sub($c) {
my $timestamp = $c->param('timestamp');
my $tag = $c->param('tag');
my $title = $c->param('title');
my $uuid = $c->param('uuid');
my $app = $c->param('app');
my $server_time = $c->param('server_time');
my $scope = $c->param('scope');
my ($db,$database,$sql) = &subs::database_grabber();
my $deletions = [];
if ($tag) {
if ($device eq 'mobile') {
`termux-notification-remove $tag`;
}
}
if ($scope eq 'all') {
my $notifications = ¬ification_grabber({ delete => 'yes' });
foreach my $n ( @{$notifications->{'list'}} ) {
&subs::db_delete('notifications', { uuid => $n->{'uuid'} });
push @{$deletions}, $n->{'uuid'};
&deletion_registration({ table => 'notifications', uuid => $n->{'uuid'}, server_time => $n->{'server_time'} });
}
}
else {
&subs::db_delete('notifications', { timestamp => $timestamp, title => $title, uuid => $uuid });
&deletion_registration({ table => 'notifications', uuid => $uuid, server_time => $server_time });
push @{$deletions}, $uuid;
}
$c->render(json => $deletions );
};
get '/manager/notifications/filter' => sub($c) {
my $app = $c->param('app');
&subs::setting_setter({ app => 'notifications', setting => 'filter', value => $app });
my $returner = notification_grabber({});
$c->render(json => $returner);
};
get '/manager/notifications/search' => sub($c) {
my $search = $c->param('search');
&subs::setting_setter({ app => 'notifications', setting => 'search', value => $search });
my $returner = ¬ification_grabber({});
$c->render(json => $returner);
};
get '/manager/notifications/scroll' => sub($c) {
my $returner = ¬ification_grabber({ scroll => 'down', position => $c->param('position') });
$c->render(json => $returner);
};
get '/manager/configure/backup_now' => sub($c) {
unless ($c->param('reason')) {
$c->param('reason' => 'backup');
}
else {
my $remote_ip = $c->tx->remote_address;
}
my $disposition = &subs::backup_now($c);
$c->render(json => $disposition);
};
post '/manager/configure/delete_backup' => sub($c) {
my $backup = $c->param('filename');
if (-e $backup) {
`shred -u $backup`;
}
$c->render(text => 'backup deleted');
};
get '/manager/appointment_viewer' => sub($c) {
my $timestamp = $c->param('timestamp');
my $readable = $c->param('readable');
my $timeshift = $c->param('timeshift');
my $scope = $c->param('scope');
my $sorts = $c->param('sorts');
my $time_machine = $c->param('time_machine');
my $filter = $c->param('filter');
my $account = $c->param('account');
my $project = $c->param('project');
my $appt_view_toggle = $c->param('appt_view_toggle');
my $layout = $c->param('layout');
my $stats = eval { return decode_json $c->param('stats') } || {};
my $timeshift_max;
my $chosen_appts;
if ($c->param('appts')) {
$chosen_appts = decode_json $c->param('appts');
}
else { $chosen_appts = \@appointments; }
if ($time_machine) {
$timestamp = &subs::ago_calc($time_machine,$timestamp);
}
if ($timeshift && $timeshift =~ /[0-9]/) {
$timestamp = &subs::ago_calc($timeshift,$timestamp);
$timestamp = $timestamp - ($timeshift);
}
my $period = &{$subs::time_subs->{$scope}}($timestamp) if eval {&{$subs::time_subs->{$scope}}($timestamp)};
my $appts = &log_reader({
appts => $chosen_appts,
project => $project,
account => $account,
scope => $scope,
sorts => $sorts,
'timestamp' => $timestamp,
filter => $filter,
appt_view_toggle => $appt_view_toggle,
view => 'appointment_viewer',
stats => $stats
});
$appts->{'__specs'}->{'layout'} = $layout;
if ($appts->{'updateable'} eq 'no') {
$c->render(json => { updateable => 'no', '__specs' => $appts->{'__specs'} });
$c->rendered;
return;
}
my @results;
my @log_watch;
foreach my $a (@{$chosen_appts}) {
next if $appts->{$a}->{'setting'}->{'visible'} eq 'unchecked';
foreach my $type (qw/list/) {
last unless $appts->{$a}->{$type};
if (@{$appts->{$a}->{$type}} && scalar @{$appts->{$a}->{$type}} > 0) {
if (my @present = grep { $_->{'timestamp'} > $period && $_->{'timestamp'} < ($timestamp + ($timestamp - $period)) } @{$appts->{$a}->{$type}}) {
$appts->{$a}->{$scope . '_occurrences'} = scalar @present;
foreach my $p (@present) {
$p->{'formatted_name'} = &subs::format_name($p->{'app'});
my $point = $p->{'timestamp'} - $period;
my $total = $timestamp - $period;
my $percent = $point / $total;
$appts->{$a}->{$scope . '_percent'} = $percent;
if ($p->{'duration'}) {
my $point = $p->{'timestamp'} - $p->{'duration'} - $period;
my $total = $timestamp - $period;
my $percent = $point / $total;
$p->{$scope . '_start_percent'} = $percent;
}
$p->{$scope . '_percent'} = $percent;
$p->{$scope . '_occurrences'} = $appts->{$a}->{$scope . '_occurrences'};
$p->{'start_notes'} = undef;
$p->{'end_notes'} = undef;
if ($p->{'type'} eq 'transaction') {
if ($p->{'amount'} && !$p->{'tax'} && $p->{'total'} > $p->{'amount'}) {
$appts->{$a}->{$scope . '_tax' } += sprintf("%.2f",($p->{'amount'} * 1.13) - $p->{'amount'});
}
$appts->{$a}->{$scope . '_tax' } += sprintf("%.2f", ($p->{'tax'})) if $p->{'tax'};
$appts->{$a}->{$scope . '_total' } += unformat_number($p->{'total'} || $p->{'amount'}) if $p->{'total'} || $p->{'amount'};
$appts->{$a}->{$scope . '_amount' } += unformat_number($p->{'amount'}) if $p->{'amount'};
}
$appts->{$a}->{$scope . '_quantity' } += $p->{'quantity'} if $p->{'_occurrences'};
$appts->{$a}->{'since'} = ($timestamp - $p->{'timestamp'}) / 1000;
if ($p->{'type'} =~ 'start|pause|record' ) {
$appts->{$a}->{'setting'}->{'status'} = $p->{'type'};
$appts->{$a}->{$scope . '_duration'} += $timestamp - $p->{'timestamp'};
$appts->{$a}->{'formatted_since'} = &subs::duration_sayer(($timestamp - $p->{'timestamp'}) / 1000);
}
else {
$appts->{$a}->{$scope . '_duration'} += abs $p->{'duration'} || $appts->{$a}->{'setting'}->{$scope . '_duration'} if (abs $p->{'duration'} || $appts->{$a}->{'setting'}->{$scope . '_duration'});
$appts->{$a}->{'formatted_since'} = &subs::duration_sayer(($timestamp - $appts->{$a}->{'last_reset'}) / 1000) if $appts->{$a}->{'last_reset'};
}
$appts->{$a}->{'formatted_since'} = 'in ' . $appts->{$a}->{'formatted_since'} if ($timestamp - $p->{'timestamp'}) < 0;
$appts->{$a}->{$scope . '_timestamp'} = $p->{'timestamp'};
if ($sorts eq 'log') {
push @{$appts->{'__logwatch'}}, $p;
}
foreach my $ts (keys %{$subs::time_subs}) {
if ($type eq 'list') {
$appts->{'__stash'}->{$ts . '_total_' . $sorts} += (unformat_number($p->{'total'} || $p->{'amount'})) if $p->{'total'} || $p->{'amount'};
}
else {
$appts->{'__stash'}->{$ts . '_total_' . $sorts} += -(unformat_number($p->{'total'} || $p->{'amount'})) if $p->{'total'} || $p->{'amount'};
}
}
$appts->{$a}->{$scope . '_duration_percent'} = ($appts->{$a}->{$scope . '_duration'} / abs &{$subs::time_subs->{$scope}}(0)) * 100 if $appts->{$a}->{$scope . '_duration'};
$appts->{$a}->{$scope . '_duration_percent'} = sprintf("%.2f",$appts->{$a}->{$scope . '_duration_percent'}) . "%" if ($appts->{$a}->{$scope . '_duration_percent'} );
}
}
}
$appts->{$a}->{$scope . '_formatted_duration'} = &subs::duration_sayer($appts->{$a}->{$scope . '_duration'} / 1000) if $appts->{$a}->{$scope . '_duration'};
}
};
$appts->{'__specs'}->{'pseudonyms'} = &pseudonym_maker('viewer','');
my $clothesline = eval { return decode_json &subs::setting_grabber({ app => '__president', setting => 'clothesline' }) } || [];
if ($c->param('background_images') eq 'on') {
$appts->{'__specs'}->{'backgrounds'} = eval { return decode_json &subs::setting_grabber({ app => 'marker', setting => 'backgrounds' }) } || [];
$appts->{'__specs'}->{'background'} = $appts->{'__specs'}->{'backgrounds'}->[rand(scalar @{$appts->{'__specs'}->{'backgrounds'}})];
}
$c->render(
json => {
appts => $appts,
timestamp => $timestamp,
newsstand => &subs::statement_grabber($appts),
clothesline => $clothesline
}
);
};
get '/manager/tasks' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $tasks = &subs::task_grabber($app);
$c->render(json => $tasks);
};
post '/manager/tasks' => sub ($c) {
my $papp = &subs::unformat_name($c->param('papp'));
my $app = &subs::unformat_name($c->param('app'));
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $name = $c->param('name');
my $value = $c->param('value');
my $colour = $c->param('colour');
my $tasks = &subs::task_writer($c,{
papp => $papp,
app => $app,
timestamp => $timestamp,
uuid => $uuid,
name => $name,
value => $value,
colour => $colour,
project => $c->param('project'),
account => $c->param('account'),
movement => $c->param('movement')
});
my $tasks_json = encode_json $tasks;
&subs::setting_setter({ app => $app, setting => 'tasks', value => $tasks_json });
$c->render(json => &subs::task_grabber($papp));
};
post '/manager/tasks/delete' => sub($c) {
my $uuid = $c->param('uuid');
my $app = $c->param('app');
my $papp = $c->param('papp');
my $tasks_json = &subs::setting_grabber({ app => $app, setting => 'tasks' }) || '[]';
my $tasks = decode_json $tasks_json;
@{$tasks} = grep { $_->{'uuid'} ne $uuid } @{$tasks};
$tasks_json = encode_json $tasks;
&subs::setting_setter({ app => $app, setting => 'tasks', value => $tasks_json });
$c->render(json => &subs::task_grabber($papp));
};
get '/manager/appointment_measures' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $timestamp = $c->param('timestamp');
my $appts = &log_reader({ app => $app, view => 'centre_view' });
$appts->{$app}->{'settings'}->{'ia'} = eval { return decode_json $appts->{$app}->{'setting'}->{'ia'} } || {};
$appts->{$app}->{'setting'}->{'app_measures'} = eval { return decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
$c->render(
template => 'apps/app_measures',
settings => $appts->{$app}->{'setting'},
a => $app,
appts => $appts
);
};
get '/manager/appointment_details' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $timestamp = $c->param('timestamp');
my $time_machine = $c->param('time_machine');
my $timeshift = $c->param('timeshift');
my $scope = $c->param('scope');
my $sorts = $c->param('sorts');
my $filter = $c->param('filter');
my $uuid = $c->param('uuid');
if ($time_machine) {
$timestamp = &subs::ago_calc($time_machine,$timestamp);
}
if ($timeshift) {
$timeshift = &subs::time_abbrev_translator($timeshift);
$timestamp = $timestamp - ($timeshift);
}
my $appts = &log_reader({ uuid => $uuid, app => $app, filter => $filter, timeshift => $timeshift, timestamp => $timestamp, sorts => $sorts, scope => $scope, view => 'appointment_details' });
my @details;
my $pseudonyms = &pseudonym_maker('viewer', '');
my $settings = $appts->{$app}->{'setting'};
$settings->{'home_plate'} = eval { return decode_json $settings->{'home_plate'} } || {};
push @details, @{$appts->{$app}->{'list'}} if $appts->{$app}->{'list'};
my $sum = scalar @details;
foreach my $d ( @details ) {
if ($d->{'files'}) {
$sum += scalar @{$d->{'files'}};
}
}
#splice @details, 10;
my $models = &subs::db_query('select * from model where app=? order by timestamp desc', $app)->hashes;
my $options = &subs::db_query('select * from option where app=? order by timestamp desc', $app)->hashes;
my $option_categories = &subs::db_query('select * from option_category where app=? order by timestamp desc', $app)->hashes;
foreach my $mo ( @{$models}, @{$options} ) {
$mo->{'characteristics'} = eval { return decode_json $mo->{'characteristics'} } || [];
if (my @oc = grep { $_->{'name'} eq 'option_category' } @{$mo->{'characteristics'}}) {
$mo->{'option_category'} = $oc[0]->{'value'};
}
else {
$mo->{'option_category'} = 'uncategorized';
}
}
my $home_plate = &subs::setting_grabber({ app => 'me', setting => 'home_plate' });
my $hp = eval { return decode_json $home_plate } || {};
foreach my $l ( @details ) {
if ($l->{'data'}) {
$l->{'data'} = eval { return decode_json $l->{'data'} } || $l->{'data'};
}
if ($l->{'duties'}) {
$l->{'duties'} = eval { return decode_json $l->{'duties'} } || [];
}
$l->{'options'} = eval { return decode_json $l->{'options'} } || [];
$l->{'model'} = eval { return decode_json $l->{'model'} } || {};
$l->{'model'}->{'home_plate'} = eval { return decode_json &subs::setting_grabber({ app => &subs::unformat_name($l->{'model'}->{'name'}), setting => 'home_plate' }) } || {};
my ($continental,$src);
if ($l->{'source_uuid'}) {
$continental = &subs::db_query('select * from continent where (app = ? and uuid like ?) or uuid like ? order by server_time',$app, $l->{'uuid'} . '%',$l->{'source_uuid'} . '%')->hashes;
my $source = &subs::db_select('appointments', undef, { uuid => $l->{'source_uuid'} })->hashes->[0];
$l->{'src'} = $source;
}
else {
$continental = &subs::db_query('select * from continent where app = ? and uuid like ? order by server_time',$app, $l->{'uuid'} . '%')->hashes;
}
$l->{'measures'} = eval { return decode_json $l->{'measures'} } || [];
my @p = grep { $_->{'name'} eq $l->{'type'} } @{$pseudonyms};
$l->{'total_distance'} = 0;
my @last_visitor;
foreach my $continent ( @{$continental} ) {
if ($continent->{'latitude'}) {
my $radius = 6372.8;
my @home_plate;
if ($l->{'model'}->{'home_plate'}->{'latitude'} && $l->{'model'}->{'home_plate'}->{'longitude'}) {
my $hp = $l->{'model'}->{'home_plate'};
@home_plate = (deg2rad($hp->{'longitude'}), deg2rad(90 - $hp->{'latitude'}));
}
elsif ($settings->{'home_plate'}->{'latitude'} && $settings->{'home_plate'}->{'longitude'}) {
my $hp = $settings->{'home_plate'};
@home_plate = (deg2rad($hp->{'longitude'}), deg2rad(90 - $hp->{'latitude'}));
}
else {
@home_plate = (deg2rad($hp->{'longitude'}), deg2rad(90 - $hp->{'latitude'}));
}
my @visitor = (deg2rad($continent->{'longitude'}), deg2rad(90 - $continent->{'latitude'}));
my $distance = sprintf("%.3f", great_circle_distance(@home_plate, @visitor, $radius));
if ($last_visitor[0]) {
my $sum_distance = great_circle_distance(@visitor, @last_visitor, $radius);
$l->{'total_distance'} += sprintf("%.3f", $sum_distance);
}
@last_visitor = @visitor;
my $metres = $distance;
push @{$l->{'distance'}}, { server_time => $continent->{'server_time'}, distance => sprintf("%2f", $metres), uuid => $continent->{'uuid'}, timestamp => $continent->{'server_time'} };
}
}
$l->{'pseudonym'} = $p[0];
if ($l->{'type'} eq 'website') {
$l->{'content'} = &subs::db_select('websites', [ 'internal_url' ], { timestamp => $l->{'timestamp'} })->{content}->{hash};
}
}
$c->render(
template => 'appointment_details',
appts => $appts,
a => $app,
details => \@details,
settings => $settings,
models => $models,
options => $options,
option_categories => $option_categories,
device => $device,
remote_machines => &subs::db_select('remote_machines', undef, { connection => 'active' })->hashes
);
};
post '/manager/delete_duty' => sub($c) {
my $duuid = $c->param('duuid');
my $server_time = $c->param('server_time');
my $app_uuid = $c->param('app_uuid');
my $app = &subs::unformat_name($c->param('app'));
my $appt = &subs::db_select('appointments', undef, { uuid => $app_uuid, app => $app })->hashes->[0];
my $duties = eval { return decode_json $appt->{'duties'} } || [];
@{$duties} = grep { $_->{'duuid'} ne $duuid } @{$duties};
my $jduties = encode_json $duties;
&subs::db_update('appointments', { duties => $jduties, server_time => &subs::rightNow() }, { app => $app, uuid => $appt->{'uuid'} });
$c->render(json => { duuid => $duuid });
};
post '/manager/configure/home_plate/save' => sub($c) {
my $app = $c->param('app');
my $uuid = $c->param('uuid');
my $app_uuid = $c->param('uuid');
my $continent = &subs::db_select('continent', undef, { uuid => $uuid })->hashes->[0];
my $homeplate = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'home_plate' }) } || {};
my $data = {
latitude => $continent->{'latitude'},
longitude => $continent->{'longitude'},
accurancy => $continent->{'accuracy'},
uuid => $uuid
};
my $jplate = encode_json $data;
&subs::setting_setter({ app => $app, setting => 'home_plate', value => $jplate });
$c->render(json => $jplate);
};
post '/manager/configure/manual_home_plate' => sub($c) {
my $setting = $c->param('setting');
my $value = $c->param('value');
my $device = $c->param('device');
my $app = $c->param('app');
my $home_plate = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'home_plate', device => $device }) } || {};
$home_plate->{$setting} = $value;
my $jplate = encode_json $home_plate;
&subs::setting_setter({ app => $app, device => $device, setting => 'home_plate', value => $jplate });
$c->render(json => $home_plate);
};
post '/manager/palette' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $duty = $c->param('duty');
my $value = $c->param('value');
my $file = $c->param('file');
my $type = $c->param('type');
my $uuid = $c->param('uuid');
my $returner = {};
my $job = { ext => '.png' };
my $image;
my $duties = eval { return decode_json $c->param('duties') } || [];
my $sd = &subs::home($config->{'start_dir'}) . &subs::random_string_creator() . $job->{'ext'};
if ($type eq 'snapshot') {
}
else {
$job = &rock_and_roll($c);
my $data = $job->{'data'};
$sd = &subs::home($config->{'start_dir'}) . &subs::random_string_creator() . $job->{'ext'};
chomp $data;
write_file($sd, $data);
}
my $original = &subs::db_select('appointments', undef, { app => $app, uuid => $uuid })->hashes;
my $files = eval { return decode_json $original->[0]->{'file'} } || [];
foreach my $d ( @{$duties} ) {
$duty = $d->{'duty'};
$value = $d->{'value'};
unless (grep { $_ eq $duty } qw/save copy/ ) {
`magick $sd -$duty $value $sd`;
}
}
if ($duty eq 'copy') {
foreach my $fi ( @{$files} ) {
my $f = $fi->{'f'};
my $tf = $fi->{'thumb'};
if ($f eq $file) {
my @folder = split '/', $f;
pop @folder;
my $folder = join '/', @folder;
my $thumb_folder = $folder . '/thumbs';
my @f = split /\./, $f;
$f[0] = &subs::random_string_creator(12);
my $nf = $folder . '/' . join '.', @f;
my $tnf = $thumb_folder . '/' . join '.', @f;
my %fil = %{$fi};
my $fil = \%fil;
$fil->{'server_time'} = &subs::rightNow();
$fil->{'uuid'} = &subs::random_string_creator(32);
$fil->{'f'} = $nf;
`cp -v $f $nf`;
if ($fil->{'thumb'}) {
$fil->{'thumb'} = $tnf;
`cp -v $tf $tnf`;
}
push @{$files}, $fil;
}
}
my $modified_file = encode_json $files;
&subs::db_update('appointments', {
server_time => &subs::rightNow(),
file => $modified_file,
encryption_standard => undef,
},
{ uuid => $uuid, app => $app });
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
}
if ($duty eq 'save') {
my $data = read_file($sd);
write_file($file, $data);
my $new_file = $file;
$new_file =~ s/\.enc$//gi;
`mv -v $file $new_file`;
my ($db) = &subs::database_grabber();
foreach my $fi ( @{$files} ) {
my $f = $fi->{'f'};
if ($f eq $file) {
$f =~ s/\.enc$//gi;
$fi->{'f'} = $f;
if ($fi->{'thumb'}) {
my $thumb = $fi->{'thumb'};
`shred -u $thumb`;
$fi = &thumbnail_creator($fi);
}
$fi->{'server_time'} = &subs::rightNow();
}
}
my $modified_file = encode_json $files;
&subs::db_update('appointments', {
server_time => &subs::rightNow(),
file => $modified_file,
encryption_standard => undef,
},
{ uuid => $uuid, app => $app });
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
}
else {
$returner->{'image'} = 'data:' . $job->{'fd'} . ';base64,' . encode_base64 read_file($sd);
}
`shred -u $sd`;
$c->render(json => $returner);
};
get '/manager/share' => sub($c) {
my $src = $c->param('src');
my $type = $c->param('type');
my $returner;
if ($device eq 'mobile') {
$returner = `termux-share -a $type -d $src`;
}
$c->render('text' => $returner);
};
get '/manager/note_retriever' => sub ($c) {
my $app_timestamp = $c->param('app_timestamp');
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $reflected_server_time = $c->param('server_time');
my $noters = &subs::db_select('appointments', ['start_notes','notes','end_notes','server_time'], { app => $app, timestamp => $app_timestamp, server_time => $reflected_server_time });
my $noteskis = $noters->hashes;
my $cred = &subs::db_select('security');
my $creds = $cred->hashes;
my $notekeeper;
foreach my $note ( @{$noteskis} ) {
my $s = $c->session('suds');
my $start_notes = &subs::note_decrypter($s, $note->{'start_notes'},$note->{'ost'}) if eval { &subs::note_decrypter($s, $note->{'start_notes'},$note->{'ost'}) };
my $notes = &subs::note_decrypter($s, $note->{'notes'},$note->{'ost'}) if eval { &subs::note_decrypter($s, $note->{'notes'},$note->{'ost'}) };
my $end_notes = &subs::note_decrypter($s, $note->{'end_notes'},$note->{'ost'}) if eval { &subs::note_decrypter($s, $note->{'end_notes'},$note->{'ost'}) };
$notekeeper = "
" . $start_notes . "
" . $notes . "
" . $end_notes;
$notekeeper =~ s/\n/
/gi;
}
$c->render(json => { notes => $notekeeper });
};
get '/manager/torch' => sub($c) {
my $torch = $c->param('torch');
my $timestamp = $c->param('timestamp');
my $returner;
if ($device eq 'mobile') {
if ($torch eq 'off') {
`termux-torch on`;
$returner = 'on';
}
else {
`termux-torch off`;
$returner = 'off';
}
}
return $c->render(text => $returner);
};
get '/manager/centre_view' => sub($c) {
my $app = eval { return decode_json $c->param('app') } || $c->param('app');
my $jp_report = eval { return decode_json $c->param('jp_report') } || {};
my $timestamp = $c->param('timestamp');
if ($app->{'source'}) {
# &subs::cache_delete({ app => $app->{'app'}, context => 'template' });
}
if ($app->{'name'}) {
&padlock_time_extender($c);
my $window = ¢re_view_grabber({ c => $c, app => $app->{'name'}, timestamp => $timestamp, jp_report => $jp_report });
if ($c->param('source') ne 'ws') {
&Websocket::send('tab', { browser_tab_id => $c->param('browser_tab_id'), not_me => 1, console => 'appointmentGrabber(\'' . $app->{'name'} . '\',\'' . $timestamp .'\',\'ws\');'});
}
# &Websocket::send('tab', { browser_tab_id => $c->stash('browser_tab_id'), app => $app, window => $window, timestamp => $timestamp, not_me => 1 });
$c->render(text => $window);
}
};
sub centre_view_grabber($data) {
my $c = $data->{'c'};
my $app = $data->{'app'};
my $timestamp = $data->{'timestamp'};
my $jp_report = $data->{'jp_report'} || [];
$app = &subs::unformat_name($app);
my $server_time = &subs::rightNow();
my $appointment = &subs::db_query('select app,server_time,timestamp from appointments where app=? LIMIT 1',$app);
if ($app) {
my $appointments = [ $app ];
#if (my $cache_data = &subs::cache_get({ context => 'template', app => $app })) {
# return $cache_data;
# return;
#}
my $appts = &log_reader({ app => $app, view => 'centre_view' });
$appts->{$app}->{'setting'}->{'app_measures'} = eval { return decode_json $appts->{$app}->{'setting'}->{'app_measures'} } || {};
my $header = &subs::appt_header_printer({ appts => $appts, app => $app, timestamp => $timestamp });
my $string = $c->render_to_string(
template => 'appointment_wrapper',
appts => $appts,
appointments => $appointments,
header => $header,
timestamp => $timestamp,
device => $device,
from => 'centre_view',
config => &subs::config_reader(),
measures => $gb::measures,
server_time => $server_time,
jp_report => $jp_report
);
my $window = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => $app, contents => $string }, $timestamp);
# &subs::cache_set({app => $app, context => 'template' }, $window);
return $window;
}
}
get '/manager/keyup_search' => sub($c) {
my $search = $c->param('search');
my $timestamp = $c->param('timestamp');
if ($search) {
my $movement;
($search,undef,$movement) = &subs::typesetter(&subs::unformat_name($search),'no');
$search = &subs::format_name($search);
my @search = split ' ', $search;
$search = join '%', @search;
$search = '%' . $search . '%';
my ($db) = &subs::database_grabber();
my $results = &subs::db_query('select DISTINCT(app) from settings where device = ? and setting=? and value = ? and app like ? LIMIT 7', $device, 'visible','checked', $search)->hashes;
my $resulted = $c->render_to_string(template => 'search/manager', results => $results);
$c->render(json => { results => $resulted, count => scalar @{$results}, timestamp => $timestamp });
}
else {
$c->render(json => { count => 0, timestamp => $timestamp });
}
};
get '/manager/search' => sub($c) {
my $search = &subs::unformat_name($c->param('search')) || &subs::unformat_name($c->param('s'));
my $chosen_appts = $c->param('chosen_appts');
my $timestamp = $c->param('timestamp');
my $appts = &log_reader({ search => $search }) if $search;
my (@s_appointments);
my ($template);
if ($search) {
while (my ($a, $value) = each %{$appts}) {
if ($a eq $search) {
unshift @s_appointments, $a unless grep { lc $_ eq lc $appts->{$a}->{'formatted_name'}} @s_appointments;
$appts->{$a}->{'header'} = &subs::appt_header_printer({ app => $a, timestamp => $timestamp });
}
elsif ($a =~ /($search)/) {
push @s_appointments, $a unless grep { lc $_ eq lc $appts->{$a}->{'formatted_name'}} @s_appointments;
$appts->{$a}->{'header'} = &subs::appt_header_printer({ app => $a, timestamp => $timestamp });
}
}
@appointments = @s_appointments;
}
else { }
$template = 'appointment_wrapper';
$appts->{'__stash'}->{'header'} = 'yes';
my $search_engines = $config->{'search_engines'};
if ($timestamp =~ /[0-9]/) {
my $contents = $c->render_to_string(
template => $template,
appointments => \@appointments,
appts => $appts,
timestamp => $timestamp,
search => $search,
device => $device,
from => 'search',
config => &subs::config_reader(),
measures => $gb::measures,
header => '',
);
$contents = &window_maker({ user_agent => $c->param('user_agent'), app => $search, title => 'search', contents => $contents },$timestamp);
$c->render(text => $contents);
}
else {
my $ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/manager/ws';
my $mail_ws_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/mail/ws';
my $paperboy_url = 'wss://' . $c->req->url->base->host . ':' . $ENV{PORT_MSG} . '/observer/ws';
my $pseudonyms = &pseudonym_maker('manager','');
$c->render(
layout => 'manager',
title => &subs::format_name($search),
template => $template,
appointments => \@appointments,
appts => $appts,
timestamp => $timestamp,
search => $search,
device => $device,
from => 'search_engine',
config => &subs::config_reader(),
measures => $gb::measures,
ws_url => $ws_url,
mail_ws_url => $mail_ws_url,
paperboy_url => $paperboy_url,
my_name => &subs::setting_grabber({ app => 'me', setting => 'my_name' }),
advertise_watching => &subs::setting_grabber({ app => 'me', setting => 'advertise_watching' }),
website => '',
pseudonyms => $pseudonyms
);
}
#&appointment_writer($c,{
# app => &subs::unformat_name($search),
# timestamp => $timestamp,
# type => 'search'
#});
};
post '/manager/configure/environment/qr' => sub ($c) {
my $app = &subs::unformat_name($c->param('app'));
my $pos = $c->param('pos');
my $qr = `qrencode -o - $pos`;
my $returner = { qr => $qr, app => $app, 'pos' => $pos };
$c->render(json => $returner);
};
post '/manager/clipboard_setter' => sub ($c) {
my $clipboard = $c->param('clipboard');
if ($device eq 'mobile') {
# `echo "$clipboard" | termux-clipboard-set`;
}
elsif ($device eq 'computer') {
# `xclip -i "$clipboard"`;
}
return $c->render(text => $clipboard);
};
get '/manager/clipboard_getter' => sub ($c) {
my $returner;
if ($device eq 'mobile') {
$returner = `termux-clipboard-get`;
}
elsif ($device eq 'computer') {
$returner = `xclip -o`;
}
$c->render(text => $returner);
};
get '/manager/search_engine_grabber' => sub($c) {
$c->render(text => &search_engine_grabber($c));
};
sub search_engine_grabber($c) {
my $search_engines;
my $timestamp = (&subs::rightNow());
my $search = $c->param('search');
my $website = $c->param('website');
my $contents = &website_grabber({
app => $c->param('app'),
search => $search,
website => $website,
timestamp => $timestamp
});
my $window_data = { app=> $c->param('app'), contents => &website_grabber($c) };
if ($c->param('view') eq 'iframe') {
$window_data->{'iframe'} = $website;
}
my ($window,$internal_url) = &window_maker($window_data, $timestamp);
return $window;
}
get '/manager/website_get' => sub ($c) {
my ($window,$internal_url) = &website_grabber({
app => $c->param('app'),
website => $c->param('website'),
timestamp => $c->param('timestamp'),
user_agent => $c->param('user_agent')
});
$c->render(json => { internal_url => $internal_url, window => $window });
};
sub website_grabber($data) {
my ($db,$database,$sql) = &subs::database_grabber();
my $app = &subs::unformat_name($data->{'app'});
my $website = $data->{'website'} || &subs::setting_grabber({ app => $app, setting => 'web' });
my $server_time = &subs::rightNow();
my $timestamp = $data->{'timestamp'};
my $user_agent = $data->{'user_agent'} || $user_agent;
my $saved_website = &subs::db_select('websites', ['app','timestamp','internal_url','url','content'], { timestamp => $timestamp, url => $website })->hash;
my $raw_html = $saved_website->{'content'};
my $ua = Mojo::UserAgent->new;
my $res = eval { $ua->get($website => {user_agent => $user_agent})->result } ;
my $internal_url = $website || $saved_website->{'internal_url'} || "No Page";
if (eval { $res->is_success } ) {
$raw_html = $res->body;
my $hs = HTML::Strip->new(
striptags => [ 'iframe','script' ],
emit_spaces => 0
);
my $content = $hs->parse( $raw_html );
$internal_url = $saved_website->{'internal_url'};
if ($saved_website->{url}) {
&subs::db_update('websites',
{
content => $raw_html,
timestamp => $timestamp,
url => $website,
internal_url => $internal_url,
server_time => $server_time
},
{
url => $website,
app => $app
}
);
}
else {
$internal_url = &subs::random_string_creator();
&subs::db_insert('websites', {
content => $raw_html,
timestamp => $timestamp,
url => $website,
internal_url => $internal_url,
app => $app,
server_time => $server_time
});
}
}
elsif (eval {$saved_website->{'internal_url'}}) {
$internal_url = $saved_website->{'internal_url'};
}
else {
$internal_url = "No Page";
}
if ($raw_html ne $saved_website->{'content'}) {
my $write = {
timestamp => $timestamp,
app => $app,
# notes => &subs::note_encrypter($c->session('suds'),$website),
type => 'web',
data => $raw_html,
server_time => &subs::rightNow(),
warranty => $data->{'warranty'} || &subs::setting_grabber({ app => $app, setting => 'warranty' }),
uuid => &subs::random_string_creator(40)
};
&subs::db_insert('appointments', $write);
}
$saved_website->{'title'} = $saved_website->{'app'} . "_web";
my $window = &window_maker($saved_website, $timestamp);
return ($window,$internal_url);
}
get '/manager/browser' => sub ($c) {
my $internal_url = $c->param('internal_url');
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
if ($internal_url eq 'none') {
$c->render(text => "None
");
}
else {
my $results = &subs::db_select('websites', ['app','content','url','internal_url'],{ internal_url => $internal_url });
my $saved_websites = $results->hashes;
my $website = $saved_websites->[-1]->{'content'};
$saved_websites->[-1]->{'title'} = $saved_websites->[-1]->{'app'} + ' website';
my $window = &window_maker($saved_websites->[-1], $timestamp);
$c->render(text => $website);
}
};
get '/manager/media_window' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $settings = &subs::settings_grabber({ app => $app });
my $id = $c->param('id');
my $misses = eval { return decode_json $c->param('misses') } || {};
if (!$misses->{$id}) {
$misses->{$id} = &subs::random_string_creator(25,"Aa");
}
my $contents = $c->render_to_string(
template => 'apps/video',
id => $id,
source => $c->param('source'),
remote_address => $c->tx->remote_address,
local_address => $c->tx->local_address,
crate => { settings => $settings },
misses => $misses
);
if ($c->param('window_maker')) {
$c->render('text' => &window_maker({ user_agent => $c->param('user_agent'), app => $app, timestamp => $c->param('timestamp'), contents => $contents }, $timestamp));
}
else {
$c->render(json => { html => $contents, settings => $settings, app => $app, timestamp => $timestamp });
}
};
get '/manager/window_maker' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $contents = $c->param('contents');
$c->render('text' => &window_maker({ user_agent => $c->param('user_agent'), app => $app, timestamp => $timestamp, contents => $contents },$timestamp));
};
sub window_maker($type,$timestamp) {
$timestamp = &subs::rightNow() unless $timestamp;
my $window = "Window";
my $app = $type->{'app'};
my $settings = &subs::settings_grabber({ app => $app });
unless ($settings->{'uuid'}) {
$settings = &subs::setting_initializer($app,$timestamp);
}
my ($db,$database,$sql) = &subs::database_grabber();
my $user_agent = $type->{'user_agent'};
my $websockets = &subs::db_query('select * from websockets where app=? and user_agent = ? and windows like ? and windows is not null order by timestamp DESC',
'tab', $user_agent, '%app":"' . $type->{'app'} . '%')->hashes;
my $jws = undef;
foreach my $w ( @{$websockets} ) {
my $ws = eval { return decode_json $w->{'windows'} } || {};
if ($ws->{$app}) {
$jws = &subs::apostrophe_escape(encode_json $ws);
last;
}
}
my $contents;
my $title;
my $drawer;
my $formatted_name = &subs::format_name($type->{'app'});
my $unformatted_name = &subs::unformat_name($type->{'app'});
my $html_name = &subs::html_name($type->{'app'});
my $http_name = &subs::http_name($type->{'app'});
my $apostrophe_escape = &subs::apostrophe_escape($type->{'app'});
my $jp = $apostrophe_escape;
if ($jp =~ /cam$|scr$|aud$/gi) {
$jp =~ s/_cam$|_scr$|_aud$//gi;
}
if ($type->{'internal_url'}) {
my $iframe_src = '"/manager/browser?internal_url=' . $type->{'internal_url'} . '×tamp='.$timestamp.'"';
$contents = '';
$title = 'browser';
}
elsif ($type->{'iframe'}) {
my $iframe_src = '"' . $type->{'iframe'} . '"';
$contents = '';
$title = 'browser';
}
else {
$contents = $type->{'contents'};
}
if ($type->{'title'}){
$title = $type->{'title'};
}
if ($settings->{'navigation'} && $settings->{'navigation'} ne 'once') {
$settings->{'navigation'} = &subs::time_abbrev_translator($settings->{'navigation'});
}
my $main_image = &subs::main_icon_maker({ app => $unformatted_name, timestamp => $timestamp, settings => $settings, size => 'tiny' });
my $pre_dimensioned = 0;
if ($settings->{'dimensions'} && ($user_agent !~ /Android/gi || $user_agent !~ /Mobile/gi)) {
$settings->{'dimensions'} = eval { return decode_json $settings->{'dimensions'} } || {};
$pre_dimensioned = 1;
}
else {
$settings->{'dimensions'} = {};
}
my $display =
'
' . $main_image . '
' . $formatted_name . '
' . $drawer . '
' . $contents . '
';
return $display;
};
get '/manager/terminal' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $whoami = `whoami`;
chomp $whoami;
my $hostname = `hostname`;
chomp $hostname;
my $settings = &subs::settings_grabber({ app => 'terminal' });
$settings->{'errors'} = eval { return decode_json $settings->{'errors'} } || [];
$settings->{'log'} = eval { return decode_json $settings->{'log'} } || [];
my $contents = $c->render_to_string(
template => 'terminal',
window_maker => 'yes',
whoami => $whoami,
hostname => $hostname,
settings => $settings
);
if ($c->param('window_maker') eq 'yes') {
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'terminal', contents => $contents }, $timestamp);
$c->render(text => $website);
}
else {
$c->render(text => $contents);
}
};
post '/manager/termina/error_report' => sub($c) {
if (1 == 0) {
my $errors = eval { return decode_json $c->param('errors') } || [];
my $browser_tab_id = $c->param('browser_tab_id');
if (scalar @{$errors} > 0) {
my $old_errors = eval { return decode_json &subs::setting_grabber({ app => 'terminal', setting => 'errors' }) } || [];
push @{$old_errors}, @{$errors};
my $jerrors = encode_json $old_errors;
&subs::setting_setter({ app => 'terminal', setting => 'errors', value => $jerrors });
}
}
my $errors = [];
$c->render(json => $errors);
};
post '/manager/window_closer' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
&subs::window_closer($app, $c->param('browser_tab_id'));
my $settings = &subs::settings_grabber({ app => &subs::unformat_name($app) });
if ($settings->{'enc'} eq 'on') {
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
}
else {
&subs::file_decrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
}
$c->render('text' => 'ok');
};
post '/manager/terminal' => sub ($c) {
my $timestamp = $c->param('timestamp');
$c->render(text => 'ok');
my $return = &subs::run_command('terminal',$c->param('command'),$timestamp);
};
get '/manager/gallery' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $shuffle = $c->param('shuffle');
my $view = $c->param('view');
my $search = $c->param('search');
my $count = $c->param('count');
my $source = $c->param('source');
my $load_images = $c->param('loadImages');
my $file_uuid = $c->param('file_uuid');
my $new_settings = eval { return decode_json $c->param('new_settings') } || {};
foreach my $ns ( keys %{$new_settings} ) {
&subs::setting_setter({ app => 'gallery', setting => $ns, value => $new_settings->{$ns} });
}
if ($view ne 'load') {
&subs::setting_setter({ app => 'gallery', setting => 'apps', value => $c->param('apps') });
&subs::setting_setter({ app => 'gallery', setting => 'search', value => $search });
&subs::setting_setter({ app => 'gallery', setting => 'view', value => $view });
&subs::setting_setter({ app => 'gallery', setting => 'count', value => $count });
}
my $settings = &subs::settings_grabber({ app => 'gallery' });
$search = $settings->{'search'};
$view = $settings->{'view'};
$count = $settings->{'count'};
my $unlock = $c->param('unlock') || $settings->{'combo_unlock'};
my $apps = eval { return decode_json $settings->{'apps'} } || [];
my $jfiles = $c->param('files');
if ($jfiles) {
push @{$apps}, 'ide';
$view = 'photo';
}
if (scalar @{$apps} == 0) {
$settings->{'home_toggled'} = 'on';
}
if (!$view) { $view = 'photo';
if ($settings->{'home_toggled'} eq 'on') {
$view = 'home';
}
}
my $permissive = 0;
if ($unlock) {
if (secure_compare(&subs::note_decrypter($c->session('suds'), $unlock), &subs::note_decrypter($c->session('suds'), &subs::setting_grabber({ app => 'gallery', setting => 'combo_unlock' })) ) ) {
$permissive = 1;
}
}
my $images = [];
my $total_files = 0;
my $total_appts = 0;
my $total_absentees = 0;
my $asettings = {};
my @chosen;
my $send_count = 0;
my $last_send = 0;
my $seen_chosen = 0;
foreach my $a ( @{$apps} ) {
$asettings->{$a} = &subs::settings_grabber({ app => $a, settings => ['main_image', 'visible' ] }) unless $asettings->{$a};
next if $asettings->{$a}->{'visible'} ne 'checked' && $permissive == 0;
my $files = [];
if ($a eq 'ide' && $jfiles) {
$files = decode_json $jfiles;
foreach my $f ( @{$files} ) {
my $jf = encode_json [{ f => $f->{'file'} }];
$f = { file => $jf, app => 'ide' };
}
$view = 'photo';
$load_images = 1;
}
else {
$files;
if ($view eq 'photo') {
if ($settings->{'search'}) {
$files = &subs::db_query('select * from appointments where (app like ? or file like ?) and file is not null order by timestamp ' . ($settings->{'scroll_direction'} || 'desc') . '',
'%' . $settings->{'search'} . '%', '%' . $settings->{'search'} . '%')->hashes;
} else {
$files = &subs::db_query('select * from appointments where file is not null and app = ? order by timestamp ' . $settings->{'scroll_direction'}, $a)->hashes;
}
if ($shuffle eq 'on') {
@{$files} = shuffle @{$files};
}
}
}
if ($view eq 'photo' && $load_images != 0) {
Mojo::IOLoop->subprocess->run_p(sub {
my ($last_appt, $last_file);
foreach my $fi ( @{$files} ) {
$total_appts++;
my $absentees = [];
$last_appt = 1 if $total_appts >= scalar @{$files};
my $filer = eval { return decode_json $fi->{'file'} } || [];
if ($settings->{'search'}) {
my $search = $settings->{'search'};
unless ($fi->{'app'} =~ /\Q$search/gi) {
@{$filer} = grep { $_->{'name'} =~ /\Q$search/gi } @{$filer};
}
}
if ($settings->{'scroll_direction'} eq 'asc') {
sort { $a->{'server_time'} cmp $b->{'server_time'} } @{$filer};
}
else {
sort { $b->{'server_time'} cmp $a->{'server_time'} } @{$filer};
}
foreach my $f ( @{$filer} ) {
$total_files++;
$f->{'app'} = $fi->{'app'};
unless (-e $f->{'f'}) {
push @{$absentees}, $f;
next;
}
$f->{'original_file'} = $f->{'f'};
my @ext = split /\./, $f->{'f'};
if (grep { $ext[-2] eq $_ || $ext[-1] eq $_ } qw/png jpg svg bmp gif mp4 webm/ ) {
$f->{'file'} = '/play?app=' . $fi->{'app'} . '&track=' . uri_encode $f->{'f'} . '×tamp=' . $fi->{'server_time'};
$f->{'type'} = $fi->{'type'} unless $f->{'type'};
$f->{'server_time'} = $fi->{'server_time'};
$f->{'timestamp'} = $fi->{'timestamp'},
$f->{'app_uuid'} = $fi->{'uuid'};
if ($f->{'uuid'} eq $file_uuid) {
$seen_chosen = 1;
}
}
push @{$images}, $f unless $fi->{'account'} eq 'gallery';
}
if (scalar @{$absentees} > 0) {
foreach my $f ( @{$absentees} ) {
@{$filer} = grep { $_->{'uuid'} ne $f->{'uuid'} } @{$filer};
&delete_file({ app => $fi->{'app'}, file_uuid => $f->{'uuid'}, app_uuid => $fi->{'uuid'} });
}
$total_absentees+= scalar @{$absentees};
}
$send_count++;
if ($total_files - $last_send > 56 || $last_appt == 1) {
my @sender;
for (my $k = $last_send; $k <= $total_files; $k++) {
push @sender, $images->[$k] if $images->[$k]->{'uuid'};
}
&Websocket::send('music', { patience => 1, browser_tab_id => $c->param('browser_tab_id'), type => 'gallery_images', count => $count, images => \@sender, seen_chosen => $seen_chosen, last_send => $last_send, total_files => $total_files });
$seen_chosen = 0;
$last_send = $total_files;
}
}
});
}
}
if ($shuffle eq 'on') {
@{$images} = shuffle @{$images};
}
my $contents = $c->render_to_string(
template => 'apps/gallery',
window_maker => 'yes',
settings => $settings,
images => $images,
view => $view,
unlock => $unlock,
permissive => $permissive,
asettings => $asettings,
apps => $apps,
count => $count,
search => $search,
c => $c
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'gallery', contents => $contents }, $timestamp);
$c->render(json => { window => $website, view => $view, images => $images, settings => $settings, apps => $apps, search => $search });
};
get '/manager/gallery/scroll' => sub($c) {
my $settings = &subs::settings_grabber({ app => 'gallery' });
my $apps = eval { return decode_json $c->param('apps') } || [];
my $unlock = $c->param('unlock');
my $search = $c->param('search');
my $count = $c->param('count');
my $count_timestamp = $c->param('count_timestamp');
my $direction = $c->param('direction');
my $first_count = $c->param('first_count');
my $returner = { apps => $apps, count => $count, count_timestamp => $count_timestamp };
my $permissive = 0;
if ($unlock) {
if (secure_compare(&subs::note_decrypter($c->session('suds'), $unlock), &subs::note_decrypter($c->session('suds'), &subs::setting_grabber({ app => 'gallery', setting => 'combo_unlock' })) ) ) {
$permissive = 1;
}
}
$returner->{'html'} = $c->render_to_string(
template => 'apps/gallery_album',
settings => $settings,
asettings => {},
permissive => $permissive,
pre_count => $count,
first_count => $first_count,
view => 'album',
apps => $apps,
load => $direction,
appts => []
);
$c->render(json => $returner);
};
get '/manager/file/information' => sub($c) {
my $file = $c->param('file');
my $app = $c->param('app');
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
my $mouse = eval { return decode_json $c->param('mouse') } || {};
my $scope = $c->param('scope');
my $timestamp = $c->param('timestamp');
my $uuid = &subs::random_string_creator(12);
my $appt = &subs::db_select('appointments', undef, { uuid => $app_uuid, app => $app })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
@{$files} = grep { $_->{'uuid'} eq $file_uuid } @{$files};
my $file = $files->[0];
if ($file->{'ocr'}) {
$file->{'ocr'} = &subs::note_decrypter($c->session('suds'), $file->{'ocr'}, $file->{'server_time'});
$file->{'ocr'} =~ s/\n/
/gi;
}
my $returner = { app => $app, mouse => $mouse, uuid => $uuid, file => $file, appt => $appt };
$returner->{'appts'} = &log_reader({ app => $app, timestamp => $appt->{'timestamp'}, filter => 'all', scope => $scope, view => 'appointment_details' });
$c->param('duty' => 'information');
my $job = &rock_and_roll($c);
$returner->{'id'} = 'file_information_' . $uuid;
$returner->{'html'} = $c->render_to_string(
template => 'file_information',
file => $file,
app => $app,
mouse => $mouse,
uuid => $uuid,
job => $job,
appt => $appt,
appts => $returner->{'appts'},
);
$c->render(json => $returner);
};
post '/manager/file/information_updater' => sub($c) {
my $attribute = $c->param('attribute');
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
my $app = $c->param('app');
my $value = $c->param('value');
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
foreach my $f ( @{$files} ) {
if ($file_uuid eq $f->{'uuid'}) {
if ($attribute eq 'warranty') {
$value = &subs::ago_calc($value, &subs::rightNow());
$appt->{'warranty'} = $value;
}
}
}
my $jf = encode_json $files;
&subs::db_update('appointments', { server_time => &subs::rightNow(), file => $jf, warranty => $appt->{'warranty'} }, { uuid => $appt->{'uuid'}, app => $appt->{'app'} });
$c->render(json => { value => $value, files => $files, appt => $appt });
};
get '/manager/cards' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $mode = &subs::setting_grabber({ app => 'cards', setting => 'mode' });
my $history = eval { return decode_json &subs::setting_grabber({ app => 'cards', setting => $mode }) } || [];
my $contents = $c->render_to_string(
template => 'cards',
history => $history,
mode => $mode
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'cards', contents => $contents }, $timestamp);
$c->render('text' => $website);
};
get '/manager/card_picker' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $new_card = $c->param('new_card');
my $tree = &subs::inventory_grabber();
my $mode = &subs::setting_grabber({ app => 'cards', setting => 'mode' });
my $history = [];
if ($mode && $mode ne 'all') {
$history = eval { return decode_json &subs::setting_grabber({ app => 'cards', setting => $mode }) } || [];
}
elsif ($mode eq 'all') {
my $cards = `ls ./public/images/cards`;
my @cards = split /\n/, $cards;
foreach my $ca ( @cards ) {
my @ca = split /\./, $ca;
my @stat = stat './public/images/cards/' . $ca;
push @{$history}, { title => $ca[0], timestamp => $stat[10] * 1000 };
}
}
my ($card,$stream,$title);
if ($new_card eq 'new') {
if ($mode eq 'day') {
$card = &card_of_the_day();
$title = $card;
$title =~ s/.png$//gi;
}
elsif ($mode eq 'week') {
$card = &card_of_the_week();
$title = $card;
$title =~ s/.png$//gi;
}
elsif ($mode eq 'month') {
$card = &card_of_the_month();
$title = $card;
$title =~ s/.png$//gi;
}
elsif ($mode eq 'year') {
$card = &card_of_the_year();
$title = $card;
$title =~ s/.png$//gi;
}
elsif ($mode eq 'spread') {
my @cards;
for (my $n = 0; $n <= 2; $n++) {
my ($ca,$car);
$ca = &random_card_picker();
$car = './public/images/cards/' . &subs::terminal_name($ca);
while (grep { $car eq $_ } @cards) {
$ca = &random_card_picker();
$car = './public/images/cards/' . &subs::terminal_name($ca);
}
$cards[$n] = $car;
my $montage_cmd = 'magick montage ' . $cards[0] . ' ' . $cards[1] . ' ' . $cards[2] . ' -';
my $montage = `$montage_cmd`;
$ca =~ s/.png$//gi;
$title .= &subs::format_name($ca) . '
';
$stream = 'data:image/png;base64,' . encode_base64 $montage;
splice @{$history}, 10;
}
}
else {
$card = &random_card_picker();
$title = $card;
$title =~ s/.png$//gi;
}
}
else {
if ($history->[0]->{'stream'}) {
$stream = $history->[0]->{'stream'};
$title = $history->[0]->{'title'};
}
else {
$card = $history->[0]->{'title'} . '.png';
$title = $history->[0]->{'title'};
}
}
if (($mode eq 'free' || $mode eq 'cycle' || $mode eq 'spread') && $new_card eq 'new') {
splice @{$history}, 40;
unshift @{$history}, { title => $title, timestamp => $timestamp, stream => $stream };
my $jhistory = eval { return encode_json $history };
&subs::setting_setter({ app => 'cards', setting => $mode, value => $jhistory });
}
foreach my $h ( @{$history} ) {
$h->{'description'} = $tree->{$h->{'title'} . '.png'};
}
my $html = $c->render_to_string(
template => 'cards',
history => $history,
mode => $mode
);
$c->render(json => {
html => $html,
description => $tree->{$card},
title => &subs::format_name($title),
filename => $card,
history => $history,
mode => $mode,
stream => $stream
});
};
sub random_card_picker() {
my $cards = `ls public/images/cards`;
my @cards = shuffle split /\n/, $cards;
@cards = shuffle grep { $_ ne 'title.png' && $_ ne 'back.png' } shuffle @cards;
my $card = $cards[rand(scalar @cards)];
return $card;
}
sub card_of_the_day() {
my $card;
my $cards = eval { decode_json &subs::setting_grabber({ app => 'cards', setting => 'day' }) } || [];
splice @{$cards}, 40;
my $last_card = $cards->[0];
$card = $last_card->{'title'};
my @time = localtime($last_card->{'timestamp'} / 1000);
my @now = localtime(&subs::rightNow() / 1000);
if ($time[3] != $now[3]) {
my $new_card = &random_card_picker();
$new_card =~ s/.png$//gi;
my $car = { title => $new_card, timestamp => &subs::rightNow() };
$card = $car->{'title'};
unshift @{$cards}, $car;
my $jcards = encode_json $cards;
&subs::setting_setter({ app => 'cards', setting => 'day', value => $jcards });
}
return $card . '.png';
}
sub card_of_the_week() {
my $card;
my $cards = eval { decode_json &subs::setting_grabber({ app => 'cards', setting => 'week' }) } || [];
splice @{$cards}, 40;
my $last_card = $cards->[0];
$card = $last_card->{'title'};
my @time = localtime($last_card->{'timestamp'} / 1000);
my @now = localtime(&subs::rightNow() / 1000);
if (sprintf("%.0f", $time[7] / 7) != sprintf("%.0f", $now[7] / 7)) {
my $new_card = &random_card_picker();
$new_card =~ s/.png$//gi;
my $car = { title => $new_card, timestamp => &subs::rightNow() };
$card = $car->{'title'};
unshift @{$cards}, $car;
my $jcards = encode_json $cards;
&subs::setting_setter({ app => 'cards', setting => 'week', value => $jcards });
}
return $card . '.png';
}
sub card_of_the_month() {
my $card;
my $cards = eval { decode_json &subs::setting_grabber({ app => 'cards', setting => 'month' }) } || [];
splice @{$cards}, 40;
my $last_card = $cards->[0];
$card = $last_card->{'title'};
my @time = localtime($last_card->{'timestamp'} / 1000);
my @now = localtime(&subs::rightNow() / 1000);
if ($time[4] != $now[4]) {
my $new_card = &random_card_picker();
$new_card =~ s/.png$//gi;
my $car = { title => $new_card, timestamp => &subs::rightNow() };
$card = $car->{'title'};
unshift @{$cards}, $car;
my $jcards = encode_json $cards;
&subs::setting_setter({ app => 'cards', setting => 'month', value => $jcards });
}
return $card . '.png';
}
sub card_of_the_year() {
my $card;
my $cards = eval { decode_json &subs::setting_grabber({ app => 'cards', setting => 'year' }) } || [];
splice @{$cards}, 40;
my $last_card = $cards->[0];
$card = $last_card->{'title'};
my @time = localtime($last_card->{'timestamp'} / 1000);
my @now = localtime(&subs::rightNow() / 1000);
if ($time[5] != $now[5]) {
my $new_card = &random_card_picker();
$new_card =~ s/.png$//gi;
my $car = { title => $new_card, timestamp => &subs::rightNow() };
$card = $car->{'title'};
unshift @{$cards}, $car;
my $jcards = encode_json $cards;
&subs::setting_setter({ app => 'cards', setting => 'year', value => $jcards });
}
return $card . '.png';
}
get '/manager/synth' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $settings = &subs::settings_grabber({ app => 'synth' });
my $piano = $gb::piano;
my $ratio = $piano->[0]->{'__specs'}->{'ratio'};
for (my $n = 2; $n <= 13; $n++) {
$piano->[$n]->{'freq'} = $piano->[$n - 1]->{'freq'} * $ratio;
}
my $contents = $c->render_to_string(
template => 'synth',
window_maker => $c->param('window_maker'),
piano => $piano,
settings => $settings
);
my $website = &Manager::window_maker({ settings => $settings, user_agent => $c->param('user_agent'), app => 'synth', contents => $contents }, $timestamp);
$c->render('text' => $website);
# &appointment_writer($c, {
# app => 'synth',
# timestamp => $timestamp,
# type => 'open',
# });
};
get '/manager/studio' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $songs = &subs::db_select('appointments', undef, { type => 'studio' })->hashes;
my $settings = &subs::settings_grabber({ app => 'studio' });
my $last_song;
foreach my $song ( @{$songs} ) {
$song->{'data'} = eval { return decode_json $song->{'data'} } || {};
if ($song->{'uuid'} eq $settings->{'last_song'}) {
$last_song = $song;
}
}
my $contents = $c->render_to_string(
template => 'studio',
window_maker => $c->param('window_maker'),
songs => $songs,
settings => $settings,
last_song => $last_song
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'studio', contents => $contents }, $timestamp);
$c->render(text => $website);
};
post '/manager/studio/save' => sub ($c) {
my $app = &subs::unformat_name($c->param('app')) || 'studio';
my $timestamp = $c->param('timestamp');
my $name = $c->param('name');
my $init = &subs::setting_initializer($app,$timestamp);
my $jdata = $c->param('studio');
my $data = eval { decode_json $jdata };
my $duration = $c->param('duration') * 1000;
my $notepad = $c->param('notepad');
my $uuid = &subs::random_string_creator(20);
my @files;
foreach my $u ( @{$c->req->uploads} ) {
my $folder = &subs::setting_grabber( { app => 'misc', setting => 'rec_location', device => $device } );
my $location = &subs::home($folder) . '/' . $app;
my $take_uuid = &subs::random_string_creator(17);
my @filename = split '_', (split /\./, $u->filename)[0];
my $channel = $filename[-2];
my $take = $filename[-1];
$data->{$channel}->{'mixer'}->{'out'}->[$take]->{'uuid'} = $take_uuid;
my $filename = $location . '/' . $u->filename;
`mkdir -p $location` unless -e $location;
$u->move_to($filename);
push @files, { f => $filename, uuid => $take_uuid, type => 'recording' };
}
my $jfile = encode_json \@files;
$jdata = encode_json $data;
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
data => $jdata,
notes => &subs::note_encrypter($c->session('suds'),$notepad),
type => 'studio',
file => $jfile,
uuid => $uuid,
duration => $duration || '1000',
server_time => &subs::rightNow()
};
# &appointment_writer($c,$write);
if ($c->param('uuid') && $c->param('uuid') ne 'undefined') {
$uuid = $c->param('uuid');
$write->{'uuid'} = $uuid;
my $song_saved = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app })->hashes->[0];
my $old_files = eval { return decode_json $song_saved->{'file'} } || [];
push @files, @{$old_files};
$write->{'file'} = encode_json \@files;
&subs::db_update('appointments', $write, { uuid => $uuid, app => $app });
}
else {
&appointment_writer($c,$write);
}
&subs::setting_setter({ app => 'studio', setting => 'last_song', value => $uuid });
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
$c->render(json => { app => $app, uuid => $uuid, studio => $data });
};
get '/manager/studio/load' => sub($c) {
my $uuid = $c->param('uuid');
my $song = &subs::db_select('appointments', undef, { type => 'studio', uuid => $uuid })->hashes->[0];
my $data = decode_json $song->{'data'};
my $misc_settings = &misc_setting_list();
$data->{'admin'}->{'name'} = $song->{'app'};
$data->{'admin'}->{'uuid'} = $song->{'uuid'};
my $files = eval { return decode_json $song->{'file'} } || [];
foreach my $d ( keys %{$data} ) {
if ($data->{$d}->{'mixer'}) {
if (eval { @{$data->{$d}->{'mixer'}->{'out'}} }) {
my $out = $data->{$d}->{'mixer'}->{'out'};
foreach my $o ( @{$out} ) {
if ($o->{'uuid'}) {
my @files = grep { $_->{'uuid'} eq $o->{'uuid'} } @{$files};
my $file = $files[0];
$o->{'src'} = '/file_open?file=' . uri_encode $file->{'f'} . '&app=' . $song->{'app'} . '×tamp=' . $song->{'server_time'};
}
}
}
}
}
&subs::setting_setter({ app => 'studio', setting => 'last_song', value => $uuid });
$c->render(json => { app => $song->{'app'}, uuid => $song->{'uuid'}, studio => $data, song => $song });
};
post '/manager/studio/delete' => sub($c) {
my $uuid = $c->param('uuid');
my $app = $c->param('uuid');
&subs::db_delete('appointments', { app => $app, uuid => $uuid, type => 'studio' });
$c->render(json => { 'status' => 'ok' });
};
get '/manager/relational' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $website = &relationalizer({
timestamp => $timestamp,
c => $c
});
$c->render(text => $website->{'window'});
};
sub relationalizer($data) {
my $timestamp = $data->{'timestamp'};
my $c = $data->{'c'};
my $settings = $data->{'settings'} || &subs::settings_grabber({ app => 'relational' });
$settings->{'open_buckets'} = eval { return decode_json $settings->{'open_buckets'} } || {};
my $all_settings = {};
my $returner = {};
$returner->{'contents'} = $c->render_to_string(
settings => $settings,
template => 'relational/relational',
window_maker => $c->param('window_maker'),
category_search => $settings->{'category_search'},
contents_search => $settings->{'contents_search'},
);
$returner->{'window'} = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'relational', contents => $returner->{'contents'} }, $timestamp);
return $returner;
}
get '/manager/relational/select' => sub($c) {
my $construct = $c->param('construct');
my $setting = $c->param('setting');
&subs::setting_setter({ 'app' => 'relational', setting => $setting, value => $construct });
my $server_time = &subs::rightNow();
my $settings = &subs::settings_grabber({ app => 'relational' });
my $relationals;
%{$relationals} = %{$gb::relationals};
foreach my $sc ( keys %{$gb::relationals} ) {
$relationals->{$sc}->{'list'} = &subs::db_select('settings', undef, { setting => 'pos', value => $gb::relationals->{$sc}->{'sing'} })->hashes;
}
my $returner = { settings => $settings, relationalizer => &relationalizer({ settings => $settings, timestamp => $server_time, c => $c }) };
$c->render(json => $returner);
};
post '/manager/relational/adder' => sub($c) {
my $construct = $c->param('construct');
my $server_time = &subs::rightNow();
my $addition = &subs::unformat_name($c->param('addition'));
my $settings = &subs::settings_grabber({ app => $addition });
if (!$settings->{'pos'}) {
$settings = &subs::setting_initializer($addition . '_' . $construct,$server_time);
}
elsif (!$settings->{'mab'} && $settings->{'pos'} ne $construct) {
&subs::setting_setter({ app => $addition, setting => 'mab', value => $construct });
$settings->{'mab'} = $construct;
}
my @constructs = grep { $_->{'sing'} eq $construct } values %{$gb::relationals};
my $pconstructs = { list => [] };
my $returner = { settings => $settings, sc => $constructs[0] };
my $relational_settings = &subs::settings_grabber({ app => 'relational' });
$returner->{'category'} = $c->render_to_string(
template => 'relational/category',
sc => $constructs[0],
all_settings => {},
settings => $settings,
pconstructs => $pconstructs,
category_search => $relational_settings->{'category_search'},
contents_search => $relational_settings->{'contents_search'},
);
$c->render(json => $returner);
};
get '/manager/relational/search' => sub($c) {
my $server_time = &subs::rightNow();
if ($c->param('search_tool') eq 'categories') {
&subs::setting_setter({ app => 'relational', 'setting' => 'category_search', 'value' => &subs::unformat_name($c->param('search')) });
}
else {
&subs::setting_setter({ app => 'relational', 'setting' => 'contents_search', 'value' => &subs::unformat_name($c->param('search')) });
}
my $settings = &subs::settings_grabber({ app => 'relational' });
my $returner = { settings => $settings, relationalizer => &relationalizer({ timestamp => $server_time, c => $c }) };
$c->render(json => $returner);
};
post '/manager/relational/sorter' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $construct = $c->param('construct');
my $b_uuid = $c->param('b_uuid');
my $b_construct = $c->param('b_construct');
my $movement = $c->param('movement');
my $bubble = &subs::settings_grabber({ uuid => $uuid });
my $bucket = &subs::settings_grabber({ uuid => $b_uuid });
$b_construct = $bucket->{'pos'};
$construct = $bubble->{'pos'};
my $sc = eval { return decode_json $bucket->{'sc_' . $construct} } || [];
push @{$sc}, $bubble->{'uuid'} unless grep { $_ eq $bubble->{'uuid'} } @{$sc};
if ($movement eq 'delete') {
@{$sc} = grep { $_ ne $bubble->{'uuid'} } @{$sc};
}
@{$sc} = grep { $_ ne 'all' } @{$sc};
my $bc = eval { return decode_json $bubble->{'sc_' . $b_construct} } || [];
push @{$bc}, $bucket->{'uuid'} unless grep { $_ eq $bucket->{'uuid'} } @{$bc};
if ($movement eq 'delete') {
@{$bc} = grep { $_ ne $bucket->{'uuid'} } @{$bc};
}
@{$bc} = grep { $_ ne 'all' } @{$bc};
my $jsc = encode_json $sc;
&subs::setting_setter({ app => $bucket->{'app'}, setting => 'sc_' . $construct, value => $jsc });
my $jbc = encode_json $bc;
&subs::setting_setter({ app => $bubble->{'app'}, setting => 'sc_' . $b_construct, value => $jbc });
$bucket->{'sc_' . $construct} = $jsc;
$bubble->{'sc_' . $b_construct} = $jbc;
$gb::relational_construct->{$construct}->{'list'} = [];
$gb::relational_construct->{$b_construct}->{'list'} = [];
my $settings = &subs::settings_grabber({ app => 'relational' });
my $returner = { movement => $movement, bucket_uuid => $bucket->{'uuid'}, bubble => $bubble, bucket => $bucket, sc => $sc, bc => $bc };
$returner->{'bucket'} = $c->render_to_string(
template => 'relational/bucket',
all_settings => {},
settings => $settings,
const => $bucket,
contents_search => $settings->{'contents_search'}
);
$returner->{'bubble'} = $c->render_to_string(
template => 'relational/bucket',
all_settings => {},
settings => $settings,
const => $bubble,
contents_search => $settings->{'contents_search'}
);
$c->render(json => $returner);
my $cd = &subs::cache_get({ app => 'relational', context => 'buckets' });
$cd->{$bucket->{'app'}} = $returner->{'bucket'};
$cd->{$bubble->{'app'}} = $returner->{'bubble'};
&subs::cache_set({ app => 'relational', context => 'buckets', warranty => '-5y' }, $cd);
};
get '/manager/twirl' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $contents = $c->render_to_string(
settings => &subs::settings_grabber({ app => 'twirl' }),
template => 'twirl',
window_maker => $c->param('window_maker')
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'twirl', contents => $contents }, $timestamp);
$c->render(text => $website);
};
get '/manager/ide' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $website = &ide_opener({ timestamp => $timestamp });
$c->render(json => $website);
};
sub ide_opener($data) {
my $timestamp = $data->{'timestamp'};
my $c = app->build_controller;
my $settings = &subs::settings_grabber({ app => 'ide' });
my $search = $data->{'search'};
my $folder = $data->{'folder'};
my $files = &subs::ide_files(&subs::home($folder) || &subs::home($settings->{'folder_selector'}) || './');
if ($search) {
my $searched_files;
foreach my $f ( @{$files} ) {
my $fi = $folder . $f->{'file'};
if ($folder ne './') { $fi = $f->{'file'}; }
my $contents;
if (-e $fi) {
$contents = read_file($fi);
}
if ($contents =~ /\Q$search/gi || $fi =~ /\Q$search/gi ) {
push @{$searched_files}, $f, unless grep { $_->{'file'} eq $f->{'file'} } @{$searched_files};
}
$files = $searched_files;
}
}
my $open_tabs = eval { return decode_json $settings->{'open_tabs'} } || {};
my $tabs = {};
foreach my $f ( keys %{$open_tabs} ) {
if ($open_tabs->{$f}->{'status'} eq 'open') {
my ($tab,$content,$file) = &ide_file_open($f,'load');
$tabs->{$f} = { tab => $tab, content => $content, file => $file};
}
}
my $bgc = &subs::setting_grabber({ app => 'misc', setting => 'ide_sidebar_container_background_colour', device => $device });
my $contents = $c->render_to_string(
files => $files,
template => 'ide',
tabs => $tabs,
window_maker => $c->param('window_maker'),
background_colour => $bgc,
misc_settings => &misc_setting_list(),
device => $device,
settings => $settings,
search => $search
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'ide', contents => $contents }, $timestamp);
return { html => $website, tabs => $tabs, settings => $settings };
}
post '/manager/ide/folder_selector' => sub($c) {
my $timestamp = $c->param('timestamp');
my $folder = $c->param('folder');
my $search = $c->param('search');
&subs::setting_setter({ app => 'ide', setting => 'folder_selector', value => $folder });
my $website = &ide_opener({ timestamp => $timestamp, folder => $folder, search => $search });
$c->render(json => $website);
};
post '/manager/ide/file_create' => sub($c) {
my $filename = &subs::terminal_name($c->param('filename'));
my $timestamp = $c->param('timestamp');
`touch $filename`;
$c->render('text' => 'ok');
};
post '/manager/ide/file_delete' => sub($c) {
my $file = &subs::terminal_name($c->param('file'));
my $type = $c->param('type');
my @ext = split /\./,$file;
if ($type eq 'file') {
my $command = 'shred -u ' . $file;
`$command`;
}
else {
`rm -R $file`;
}
$c->render(json => { file => $file, type => $type });
};
get '/manager/ide/file_open' => sub($c) {
my $timestamp = $c->param('timestamp');
my $file = $c->param('file');
my $location = $c->param('location');
my @file = split /\./, $file;
my $files;
my $open_app;
if ($file[-1] eq 'enc') {
pop @file;
}
if (grep { $_ eq $file[-1] } qw/jpeg jpg png bmp tiff mpg webm webv/) {
$open_app = 'gallery';
my @folder = split '/', $file;
pop @folder;
my $folder = join '/', @folder;
my @files = split /\n/, `ls $folder`;
foreach my $fi ( @files ) {
if ($location eq './') {
$fi = $gb::pwd . '/' . $fi;
}
else {
$fi = $folder . '/' . $fi;
}
next if -d $fi;
my @stat = stat($fi);
my $temp = {};
$temp->{'size'} = $stat[7];
$temp->{'modified'} = $stat[9];
$temp->{'created'} = $stat[10];
$temp->{'accessed'} = $stat[8];
my $f = { f => $fi, app => 'ide', file => $fi, server_time => $temp->{'created'} * 1000 };
unless ($f->{'file'} =~ /base64/gi) {
if ($f->{'file'} =~ /png|jpg|svg|bmp|gif|mp4|webm/) {
$f->{'file'} = '/play?app=' . $f->{'ide'} . '&track=' . uri_encode $f->{'file'} . '×tamp=' . $f->{'server_time'};
}
}
push @{$files}, $f;
}
}
my ($seen,@before,@after);
foreach my $f ( @{$files} ) {
if ( $file eq $f->{'f'} ) {
$seen = 1;
}
if ($seen != 1) {
unshift @before, $f;
}
else {
unshift @after, $f;
}
}
@{$files} = (@before, @after);
my ($tab,$content,$f);
if ($seen != 1) {
($tab,$content,$f) = &ide_file_open($file,'open');
}
my $open_tabs = eval { return decode_json &subs::setting_grabber({ app => 'ide', setting => 'open_tabs' }) } || {};
$open_tabs->{$file} = { status => 'open' };
my $ot = encode_json $open_tabs;
&subs::setting_setter({ app => 'ide', setting => 'open_tabs', value => $ot });
$c->render(json => { content => $content, tab => $tab, file => $file, open_app => $open_app, files => $files });
};
sub ide_file_open($file,$source) {
my $content = `cat $file`;
my @file_name = split '/', $file;
my $status = '';
if ($source eq 'open') {
$status = 'active';
}
my $tab = '' . $file_name[-1] . '';
return ($tab,$content,$file);
}
post '/manager/ide/file_close' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $file = $c->param('file');
my $open_tabs = eval { return decode_json &subs::setting_grabber({ app => 'ide', setting => 'open_tabs' }) } || {};
$open_tabs->{$file} = { status => 'closed' };
my $ot = encode_json $open_tabs;
&subs::setting_setter({ app => 'ide', setting => 'open_tabs', value => $ot });
};
post '/manager/ide/save' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $file = $c->param('file');
my $content = $c->param('content');
write_file($file, $content);
$c->render(json => { status => 'success' });
};
get '/manager/mailbox' => sub ($c) {
my $timestamp = $c->param('timestamp');
my ($db,$database,$sql) = &subs::database_grabber();
my $contents = &mail_checker($c)->{'contents'};
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'mailbox', contents => $contents }, $timestamp);
$c->render(text => $website);
# &appointment_writer($c, {
# app => 'mailbox',
# timestamp => $timestamp,
# type => 'open'
# });
};
get '/manager/mail/picker' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $contents = &mail_checker($c)->{'contents'};
my $returner = { html => &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'mailbox', contents => $contents }, $timestamp) };
$c->render(json => $returner);
};
get '/manager/mail/contact' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $contents = &mail_checker($c)->{'contents'};
my $returner = { html => &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'mailbox', contents => $contents }, $timestamp) };
$c->render(json => $returner);
};
get '/manager/mail/phone' => sub($c) {
my $timestamp = $c->param('timestamp');
my $contents = &mail_checker($c)->{'contents'};
my $returner = { html => &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'mailbox', contents => $contents }, $timestamp) };
$c->render(json => $returner);
};
get '/manager/mail/email' => sub($c) {
my $timestamp = $c->param('timestamp');
my $contents = &mail_checker($c)->{'contents'};
my $returner = { html => &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'mailbox', contents => $contents }, $timestamp) };
$c->render(json => $returner);
};
get '/manager/mail/compose' => sub($c) {
my $email = $c->param('email');
my $draft = &subs::db_select('mailbox', undef, { email => $email, status => 'draft' })->hashes->[0];
foreach my $e ( qw/email subject body/ ) {
$draft->{$e} = &subs::note_decrypter($c->session('suds'), $draft->{$e});
}
my $content = $c->render_to_string(
template => 'mail/email_compose',
email => $email,
draft => $draft
);
$c->render(json => {
email => $email,
html => $content,
draft => $draft
});
};
get '/manager/mail/scroll' => sub($c) {
my $mc = &mail_checker($c);
$c->render(json => $mc);
};
sub mail_checker($c) {
my ($db,$database,$sql) = &subs::database_grabber();
my $incoming_data = eval { return decode_json $c->param('incoming_data') } || {};
my $bgc = &subs::setting_grabber({ app => 'misc', setting => 'mail_sidebar_container_background_colour', device => $device });
my $contacters = &subs::db_query('select * from tickets');
my $timestamp = $c->param('timestamp') || &subs::rightNow();
my $contacts = $contacters->hashes;
my $picker = eval { return decode_json $c->param('picker') } || {};
my $settings = &subs::settings_grabber({ app => 'mail' });
my $me = &manager_file_maker($c->session('name'));
$settings->{'mail_config'} = eval {return decode_json $settings->{'mail_config'} } || {};
foreach my $contact ( @{$contacts} ) {
$contact->{'contact_name'} = lc &manager_file_maker($contact->{'name'});
$contact->{'app'} = $contact->{'contact_name'};
}
my $contact = $c->param('mail_contact');
my $phone = $c->param('phone');
my $email = $c->param('email');
my $main_title;
if ($c->session('privilege') eq 'guest') {
$contact = $c->session('ticket_uuid');
}
my $last_sc;
foreach my $scons ( sort { $a->{'order'} cmp $b->{'order'} } values %{$gb::social_constructs} ) {
my $sc = $scons->{'name'};
if (1 == 1 || $scons->{'order'} == 0 || scalar @{$gb::social_constructs->{$last_sc}->{'list'}} > 0) {
my $construct = &subs::db_query('select * from settings where setting=? and value=?', 'pos', $gb::social_constructs->{$sc}->{'sing'});
$gb::social_constructs->{$sc}->{'list'} = $construct->hashes;
$gb::social_constructs->{$sc}->{'value'} = $picker->{$sc};
$last_sc = $sc;
}
}
my $list = [];
my $q;
if ($settings->{'subsection'} eq 'list') {
my $listing = &subs::db_query('select * from mailbox where timestamp < ?', $timestamp)->hashes;
foreach my $l ( @{$listing} ) {
my $seen = 0;
foreach my $soc_con ( keys %{$gb::social_constructs} ) {
my @ls = grep { $_->{$gb::social_constructs->{$soc_con}->{'sing'}} eq $l->{$gb::social_constructs->{$soc_con}->{'sing'}} } @{$list};
if (scalar @ls > 0) { $seen++; }
}
if ($seen < scalar keys %{$gb::social_constructs}) {
my $uuid;
foreach my $sc ( sort keys %{$gb::social_constructs} ) {
$uuid .= $l->{$gb::social_constructs->{$sc}->{'sing'}} . '---';
}
$l->{'uuid'} = $uuid;
$l->{'config'} = $settings->{'mail_config'}->{$uuid};
push @{$list}, $l;
}
}
my @selection = split '---', $settings->{'mail_list'};
$q = &subs::db_query('select * from mailbox where timestamp < ? and account=? and club = ? and community = ? and person = ? and project = ? and team = ? order by timestamp desc LIMIT 30',
$timestamp,
$selection[0],
$selection[1],
$selection[2],
$selection[3],
$selection[4],
$selection[5],
);
foreach my $s ( @selection ) {
$main_title .= &subs::format_name(&subs::shorthand_name($s,50)) . ' ';
}
}
elsif ($settings->{'subsection'} eq 'pen') {
$q = &subs::db_query('select * from mailbox where timestamp < ? and contact = ? order by timestamp desc LIMIT 30', $timestamp, 'pen');
$main_title = 'Pen';
}
elsif ($phone) {
$q = &subs::db_query('select * from mailbox where timestamp < ? and phone = ? order by timestamp desc LIMIT 30', $timestamp, $phone);
$main_title = &subs::format_name(&subs::db_select('settings', undef, { setting => 'phone', value => $phone })->hashes->[0]->{'app'}) . ' ' . $phone;
}
elsif ($email) {
$q = &subs::db_query('select * from mailbox where timestamp < ? and email = ? order by timestamp desc LIMIT 30', $timestamp, $email);
$main_title = &subs::format_name(&subs::db_select('settings', undef, { setting => 'email', value => $email })->hashes->[0]->{'app'}) . ' ' . $email;
}
elsif ($contact) {
$q = &subs::db_query('select * from mailbox where timestamp < ? and contact = ? order by timestamp desc LIMIT 30', $timestamp, $contact);
my @cont = grep { $_->{'uuid'} eq $contact } @{$contacts};
$main_title = &subs::format_name($cont[0]->{'name'});
}
else {
$q = &subs::db_query('select * from mailbox where timestamp < ? and project=? and account = ? and community = ? and team = ? and club = ? and person = ? order by timestamp desc LIMIT 30',
$timestamp,
($picker->{'projects'} || $gb::social_constructs->{'projects'}->{'def'}),
($picker->{'accounts'} || $gb::social_constructs->{'accounts'}->{'def'}),
($picker->{'communities'} || $gb::social_constructs->{'communities'}->{'def'}),
($picker->{'teams'} || $gb::social_constructs->{'teams'}->{'def'}),
($picker->{'clubs'} || $gb::social_constructs->{'clubs'}->{'def'}),
($picker->{'people'} || $gb::social_constructs->{'people'}->{'def'}),
);
$main_title = &subs::format_name(($picker->{'projects'} || $gb::social_constructs->{'projects'}->{'def'}) . ' ' .
($picker->{'accounts'} || $gb::social_constructs->{'accounts'}->{'def'}) . ' ' .
($picker->{'communities'} || $gb::social_constructs->{'communities'}->{'def'}) . ' ' .
($picker->{'teams'} || $gb::social_constructs->{'teams'}->{'def'}) . ' ' .
($picker->{'clubs'} || $gb::social_constructs->{'clubs'}->{'def'}) . ' ' .
($picker->{'people'} || $gb::social_constructs->{'people'}->{'def'}));
}
my $mails = $q->hashes;
Mojo::IOLoop->subprocess->run_p(sub {
foreach my $m ( @{$mails} ) {
if ($m->{'status'} eq 'public' && $c->session('privilege') eq 'citizen') {
&subs::db_query('update mailbox set status=?, body =? where uuid =?', 'sent', &subs::note_encrypter($c->session('suds'), $m->{'body'}, $m->{'timestamp'}), $m->{'uuid'});
}
else {
$m->{'body'} = &subs::note_decrypter($c->session('suds'),$m->{'body'},$m->{'ost'});
}
$m->{'decrypted'} = 'yes';
my $content = $c->render_to_string(
template => 'mail/message',
'm' => $m,
me => $me
);
&Websocket::send('mailbox', { type => 'mailbox_message', selector => '.mailbox_message[uuid="' . $m->{'uuid'} . '"]', content => $content, browser_tab_id => $c->param('browser_tab_id') });
}
});
my $combined_data = {
template => 'mail/mailbox',
mail => $mails,
window_maker => $c->param('window_maker'),
background_colour => $bgc,
contacts => $contacts,
sc => $gb::social_constructs,
mail_contact => $c->param('mail_contact'),
mail_phone => $phone,
mail_email => $email,
config => &subs::config_reader(),
settings => $settings,
list => $list,
me => $me,
incoming_data => $incoming_data,
main_title => $main_title
};
my $contents = $c->render_to_string(
%{$combined_data}
);
return { contents => $contents, mail => $mails };
}
get '/manager/mail/config' => sub ($c) {
my $uuid = $c->param('uuid');
my $configure = eval { return decode_json &subs::setting_grabber({ app => 'mail', setting => 'mail_config' }) } || {};
my $returner = { config => $configure->{$uuid} };
if ($configure->{$uuid}->{'qr'}) {
my $qr = $configure->{$uuid}->{'qr'};
$qr = `qrencode -o - $qr`;
$configure->{$uuid}->{'qr_image'} = 'data:image/png;base64,' . encode_base64($qr);
}
$returner->{'html'} = $c->render_to_string(
template => 'mail/config',
configure => $configure->{$uuid},
uuid => $uuid
);
$c->render(json => $returner);
};
post '/manager/mail/config' => sub ($c) {
my $uuid = $c->param('uuid');
my $setting = $c->param('setting');
my $value = $c->param('value');
my $configure = eval { return decode_json &subs::setting_grabber({ app => 'mail', setting => 'mail_config' }) } || {};
$configure->{$uuid}->{$setting} = $value;
my $jset = encode_json $configure;
&subs::setting_setter({ app => 'mail', setting => 'mail_config', value => $jset });
$c->render(json => $configure);
};
get '/manager/mail/qr_generator' => sub ($c) {
my $uuid = $c->param('uuid');
my $returner = {};
my $configure = eval { return decode_json &subs::setting_grabber({ app => 'mail', setting => 'mail_config' }) } || {};
my $rand = 0;
until ($rand > 200) {
$rand = rand(359);
}
$configure->{$uuid}->{'qr'} = $uuid . ' ' . &subs::random_string_creator($rand);
my $jset = encode_json $configure;
&subs::setting_setter({ app => 'mail', setting => 'mail_config', value => $jset });
if ($configure->{$uuid}->{'qr'}) {
my $qr = $configure->{$uuid}->{'qr'};
$qr = `qrencode -o - $qr`;
$configure->{$uuid}->{'qr_image'} = 'data:image/png;base64,' . encode_base64($qr);
}
$c->render(json => $configure->{$uuid});
};
get '/mail/homepage_form' => sub ($c) {
my $timestamp = $c->param('timestamp');
$c->render('text' => &mail_checker($c)->{'contents'} ,timestamp => $timestamp );
};
get '/manager/travel' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $contents = &travel_grabber($c);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'travel', contents => $contents }, $timestamp);
$c->render(text => $website);
};
sub travel_grabber($c) {
my $timestamp = $c->param('timestamp');
my $home_plate = &subs::setting_grabber({ app => 'me', setting => 'home_plate' });
my $settings = &subs::settings_grabber({ app => 'travel' });
my $travel_scope = $settings->{'travel_scope'} || 100;
my $time_scope = $settings->{'time_scope'} || '5minute';
my $home_plate_enabled = $settings->{'home_plate_enabled'};
$settings->{'maps'} = eval { return decode_json $settings->{'maps'} } || [];
my $contents = $c->render_to_string(
template => '/travel/travel',
home_plate => $home_plate,
home_plate_enabled => $home_plate_enabled,
travel_scope => $travel_scope,
time_scope => $time_scope,
window_maker => $c->param('window_maker'),
timestamp => $timestamp,
settings => $settings
);
return $contents;
}
get '/manager/travel/viewer' => sub($c) {
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $travel_scope = $c->param('travel_scope') ? $c->param('travel_scope') : 20;
my $time_scope = $c->param('time_scope') ? $c->param('time_scope') : '5minute';
my $t = &{$subs::time_subs->{$time_scope}}($timestamp); #timestamp at beginning
my $t1 = ($timestamp - $t);
my $t2 = ($t1 + $timestamp);
my ($db,$database,$sql) = &subs::database_grabber();
my $map = $c->param('map');
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
my ($main_map,$home_bases);
@{$main_map} = grep { $_->{'uuid'} eq $map } @{$maps};
$main_map = $main_map->[0];
my $proxies = { current_map => $main_map, near => [], far => [], here => {}, scope => $time_scope, travel_scope => $travel_scope };
my $locations = [];
if (&subs::setting_grabber({ app => 'travel', setting => 'home_plate_enabled' }) eq 'enabled') {
my $home_plates = &subs::db_select('settings', undef, { setting => 'home_plate' })->hashes;
foreach my $hp ( @{$home_plates} ) {
my $ho = eval { return decode_json $hp->{'value'} } || {};
$ho->{'app'} = $hp->{'app'};
push @{$locations}, $ho;
}
}
else {
my $q = &subs::db_query('select * from continent where timestamp >= ? and timestamp <= ?', $t, $t2);
$locations = $q->hashes;
}
sub NESW { deg2rad($_[0]), deg2rad(90 - $_[1]) }
&subs::setting_setter({ app => 'travel', setting => 'travel_scope', value => $travel_scope });
&subs::setting_setter({ app => 'travel', setting => 'time_scope', value => $time_scope });
my $universal_settings = {};
$main_map->{'home_plate'}->{'app'} = $main_map->{'home_plate'}->{'legend'};
my @home_plate = NESW($main_map->{'home_plate'}->{'longitude'}, $main_map->{'home_plate'}->{'latitude'});
foreach my $sl (@{$locations}) {
$universal_settings->{$sl->{'app'}} = &subs::settings_grabber({ app => $sl->{'app'} }) unless $universal_settings->{$sl->{'app'}};
$sl->{'settings'} = $universal_settings->{$sl->{'app'}};
next if $sl->{'settings'}->{'visible'} ne 'checked';
my $radius = 6372.8;
my @visitor = NESW($sl->{'longitude'}, $sl->{'latitude'});
$sl->{'rad'} = clone \@visitor;
$sl->{'rad'}->[2] = 2;
my $distance = great_circle_distance(@home_plate, @visitor, $radius);
my $metres = $distance * 1000;
my $direction = great_circle_direction(@home_plate, @visitor);
my @destination = great_circle_destination(@home_plate,$distance,$direction);
$sl->{'direction'} = rad2deg($direction);
$sl->{'destination'} = \@destination;
$sl->{'distance'} = sprintf("%2f", $metres);
$sl->{'home_plate'} = $main_map->{'home_plate'};
push @{$proxies->{'near'}}, $sl;
if ($metres <= $travel_scope) {
}
elsif ($metres == 0) {
}
}
push @{$proxies->{'near'}}, $main_map->{'home_plate'};
$proxies->{'here'} = $main_map->{'home_plate'};
$proxies->{'html'} = $c->render_to_string(
template => 'travel/proxy',
proxies => $proxies,
start_time => $t,
end_time => $t2
);
$c->render(json => $proxies);
};
get '/manager/handbook/:chapter' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $chapter = $c->stash('chapter') || 'handbook';
my $settings = &subs::settings_grabber({ app => 'handbook' });
$settings->{'diagrams'} = eval { return decode_json $settings->{'diagrams'} } || [];
my $page = $c->param('page') || 'i';
my $template = 'handbook/handbook';
my $contents = $c->render_to_string(
template => $template,
layout => 'handbook',
page => $page,
chapter => $chapter,
window_maker => $c->param('window_maker')
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'handbook', contents => $contents }, $timestamp);
$c->render(text => $website);
# &appointment_writer($c, {
# app => 'handbook',
# timestamp => $timestamp,
# type => 'open'
# });
};
get '/manager/security' => sub ($c) {
my $contents = &security_initializer($c);
my $timestamp = $c->param('timestamp');
if ($c->param('window_maker')) {
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'security', contents => $contents }, $timestamp);
$c->render(text => $website);
}
else {
$c->render(text => $contents);
}
};
sub security_initializer($c) {
my $timestamp = $c->param('timestamp') || &subs::rightNow();
my $neighbour_link = &subs::db_select('neighbour_link')->hashes;
my $president = &subs::settings_grabber({ app => '__president' });
if ($c->param('security_view')) {
$president->{'security_view'} = $c->param('security_view');
}
my $contents = $c->render_to_string(
president => $president,
template => 'security',
window_maker => $c->param('window_maker'),
neighbour_link => $neighbour_link
);
my $padlocker = &subs::db_select('security', undef, { level => 'padlock' })->hashes || [];
if (scalar @{$padlocker} == 0) {
&subs::db_delete('settings', { app => '__president', setting => 'pl_time' });
&subs::db_delete('settings', { app => '__president', setting => 'padlock_pulls' });
}
return $contents;
}
post '/manager/security/neighbour_link_assign' => sub($c) {
my $remote_address = $c->param('remote_address');
my $local_address = $c->param('local_address');
my $privilege = $c->param('privilege');
my $name = $c->param('my_name');
my $credential = $c->param('credential');
my $data = {
initiator => $remote_address,
initiated => $local_address,
server_time => &subs::rightNow(),
name => $name,
status => $privilege,
uuid => &subs::random_string_creator(252),
credential => &subs::encrypter($c->session('suds'),$credential)
};
&subs::db_insert('neighbour_link', $data);
$c->render('text' => 'ok');
};
post '/manager/security/neighbour_link_privilege' => sub($c) {
my $privilege = $c->param('privilege');
my $uuid = $c->param('uuid');
my $server_time = &subs::rightNow();
if ($uuid) {
&subs::db_update('neighbour_link', { status => $privilege, server_time => $server_time }, { uuid => $uuid });
}
$c->render(text => &security_initializer($c));
};
post '/manager/security/neighbour_link_delete' => sub($c) {
my $uuid = $c->param('uuid');
if ($uuid) {
&subs::db_delete('neighbour_link', { uuid => $uuid });
}
$c->render(text => &security_initializer($c));
};
post '/manager/security/padlock' => sub($c) {
my $timestamp = $c->param('timestamp');
my $combo = $c->param('combo');
my $pulled = $c->param('pulled');
my ($j_pulled,$salt,$salty,$saved_pulled);
my ($db) = &subs::database_grabber();
my $padlocker = &subs::db_select('security', undef, { level => 'padlock' })->hashes || [];
my $padlock = $padlocker->[0];
$pulled = eval { return decode_json $pulled } || [];
if (scalar @{$padlocker} > 0 && scalar @{$pulled} == 0) {
$c->render(json => { status => 'failed cuz 0'});
}
if (scalar @{$pulled} > 0 && scalar @{$padlocker} > 0) {
$j_pulled = eval { return encode_json $pulled };
$salty = join '', @{$pulled};
$saved_pulled = &subs::note_decrypter($salty . $c->session('suds') . $salty, $padlock->{'credential'});
}
if ((scalar @{$padlocker} == 0) || (secure_compare( $j_pulled, $saved_pulled )) ) {
$combo = eval { return decode_json $combo };
$salt = join '', @{$combo};
my $combination = eval { return encode_json $combo };
$combo = &subs::note_encrypter($salt . $c->session('suds') . $salt,$combination);
my $activity_timeout = &subs::setting_grabber({ app => 'me', setting => 'activity_timeout' }) || '2h';
$activity_timeout = &subs::time_abbrev_translator($activity_timeout);
$c->session('padlock', $activity_timeout);
&subs::db_delete('security', { level => 'padlock' });
&subs::db_insert('security', { level => 'padlock', credential => $combo, timestamp => $timestamp, server_time => &subs::rightNow(), uuid => &subs::random_string_creator(30) });
$c->render(json => { status => 'saved' });
}
else {
$c->render(json => { status => 'failed cuz different'});
}
};
post '/manager/security/padlock/delete' => sub ($c) {
&subs::db_delete('security', { level => 'padlock' });
&subs::db_delete('settings', { app => '__president', setting => 'pl_time' });
&subs::db_delete('settings', { app => '__president', setting => 'padlock_pulls' });
$c->render(text => 'ok');
};
post '/manager/security/padlock_pull' => sub($c) {
my $timestamp = $c->param('timestamp');
my $mode = $c->param('mode');
my $digits = eval { return decode_json $c->param('digits') } || [];
my $salt = join '', @{$digits};
my $padlock = &subs::db_select('security', undef, { level => 'padlock' })->hashes->[0];
unless ($padlock->{'credential'}) {
&subs::db_delete('settings', { app => '__president', setting => 'pl_time' });
&subs::db_delete('settings', { app => '__president', setting => 'padlock_pulls' });
}
my $combo = &subs::note_decrypter($salt . $c->session('suds') . $salt, $padlock->{'credential'});
my $attempts = &subs::note_decrypter($c->session('suds'), &subs::setting_grabber({ app => '__president', setting => 'padlock_pulls' })) || 0;
$attempts += 1;
if ($attempts > 5) {
&Websocket::send('server', { console => 'leave()' });
}
if (my $combination = eval { return decode_json $combo }) {
my $success = 0;
for (my $n = 0; $n <= 2; $n++) {
if ($digits->[$n] == $combination->[$n]) {
$success = 1;
}
if ($success == 0) {
last;
}
}
if ($success == 1) {
$attempts = 0;
my $activity_timeout = &subs::setting_grabber({ app => 'me', setting => 'activity_timeout' }) || '2h';
$activity_timeout = abs &subs::time_abbrev_translator($activity_timeout);
my $new_timeout = &subs::rightNow() + $activity_timeout;
$c->session('pl_time' => $new_timeout);
if ($mode eq 'gallery') {
my $combo_unlock = &subs::note_encrypter($c->session('suds'), &subs::random_string_creator(255));
&subs::setting_setter({ app => 'gallery', setting => 'combo_unlock', value => $combo_unlock });
&Websocket::send('server', { console => '$("#gallery").attr("unlock", "' . $combo_unlock .'")', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('server', { console => 'imageViewer({ "view":"home" })', browser_tab_id => $c->param('browser_tab_id') });
}
if ($mode eq 'music') {
my $combo_unlock = &subs::note_encrypter($c->session('suds'), &subs::random_string_creator(255));
&subs::setting_setter({ app => 'music', setting => 'combo_unlock', value => $combo_unlock });
&Websocket::send('server', { console => '$("#music").attr("unlock", "' . $combo_unlock .'")', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('server', { console => 'searchMusic()', browser_tab_id => $c->param('browser_tab_id') });
}
else {
&Websocket::send('server', { console => '$(\'#padlock_frame\').html(\'\'); $(\'#padlock_frame\').hide();$(\'#everything\').show();'});
&subs::setting_setter({ app => '__president', setting => 'pl_time', value => &subs::encrypter($c->session('suds'), $new_timeout) });
}
$c->render(json => { status => 'success', pulled => $combo });
&remote_relay_request($c);
}
}
else {
if ($device eq 'mobile') {
$c->stash('app' => 'customs');
&take_picture($c, {
app => 'customs',
camera => 1
});
&take_picture($c, {
app => 'customs',
camera => 0
});
}
else {
&take_picture($c, {
app => 'customs',
camera => 'webcam'
});
}
$c->session('app' => undef);
$c->render(json => { status => 'fail' });
}
$attempts = &subs::note_encrypter($c->session('suds'),$attempts);
&subs::setting_setter({ app => '__president', setting => 'padlock_pulls', value => $attempts });
};
sub padlock_time_extender($c) {
# Mojo::IOLoop->subprocess->run_p(sub {
my $session_timeout = $c->session('pl_time');
my $server_time = &subs::rightNow();
my $padlock = &subs::db_select('security', undef, { level => 'padlock' })->hashes;
if ($c->session('authentication') eq 'approved' && $session_timeout > $server_time && scalar @{$padlock} > 0) {
my $attempts = &subs::note_decrypter($c->session('suds'), &subs::setting_grabber({ app => '__president', setting => 'padlock_pulls' }));
if ($attempts < 5) {
my $activity_timeout = &subs::setting_grabber({ app => 'me', setting => 'activity_timeout' }) || '2h';
$activity_timeout = abs &subs::time_abbrev_translator($activity_timeout);
my $padlock_time = &subs::decrypter($c->session('suds'), &subs::setting_grabber({ app => '__president', setting => 'pl_time' }) );
if ($padlock_time > $server_time) {
my $new_time = $server_time + $activity_timeout;
&subs::setting_setter({ app => '__president', setting => 'pl_time', value => &subs::encrypter($c->session('suds'), $new_time) });
$c->session('pl_time' => $new_time);
}
}
}
# });
}
sub sms_message_send($digits,$message) {
$digits =~ s/\S\d(?=\d{10})//;
if (&subs::device_setter() eq 'mobile') {
if ( $digits ) {
$message =~ s/\$/\\\$/gi;
`termux-sms-send -n $digits "$message"`;
}
}
else {
Mojo::IOLoop->subprocess->run_p(sub {
my $remote_machines = &subs::db_query('select * from remote_machines where connection=? and device=?', 'active', 'mobile')->hashes;
foreach my $rm ( @{$remote_machines} ) {
$rm = &remote_useragent_maker({ ip => $rm->{'ip'}, signatorial => $rm->{'signatorial'}, rm => $rm });
my $res = $rm->{'ua'}->post($rm->{'manager'} . '/manager/sms/message?digits=' . $digits . '&message=' . uri_encode $message);
if (eval {decode_json $res}) {
next;
}
}
});
}
return ($digits,$message);
}
post '/manager/sms/message' => sub($c) {
my $digits = $c->param('digits');
my $message = $c->param('message');
my $sms = &sms_message_send($digits,$message);
$c->render(json => $sms);
};
get '/manager/configure/sms_list_check' => sub ($c) {
my $returner = &subs::sms_list_check();
$c->render(text => $returner);
};
post '/manager/delete_app' => sub($c) {
my $app = $c->param('app');
# &subs::cache_delete({ app => $app, context => 'template' });
my $uuid = $c->param('uuid');
my $timestamp = $c->param('timestamp');
my $type = $c->param('type');
my $server_time = $c->param('server_time');
my $deleter = &delete_app($app,$uuid,$server_time,'manual delete');
&padlock_time_extender($c);
my $cv = ¢re_view_grabber({ c => $c, app => &subs::unformat_name($app), timestamp => $timestamp });
$c->render(json => { centre_view => $cv, deleter => $deleter });
};
sub delete_app($app,$uuid,$server_time,$reason) {
my $appt = &subs::db_select('appointments', undef, { uuid => $uuid, app => $app, server_time => $server_time });
my $appts = $appt->hashes;
my $status = '';
if (scalar @{$appts} > 0) {
foreach my $app ( @{$appts} ) {
$status = $app->{'type'};
&subs::db_delete('continent', { app => $app->{'app'}, uuid => $app->{'uuid'} });
&subs::db_query('delete from continent where app = ? and uuid like ?', $app->{'app'}, $app->{'uuid'} . '%' );
if ($app->{'file'} && $app->{'source'} ne 'music' && $app->{'account'} ne 'gallery' && $app->{'type'} ne 'view' && $app->{'type'} ne 'listen') {
my $filings = eval { return decode_json $app->{'file'} } || [];
foreach my $f (@{$filings}) {
my $filing = $f->{'f'};
&delete_file({ app => $app->{'app'}, app_uuid => $uuid, file_uuid => $f->{'uuid'}, reason => 'delete_app' });
}
}
&subs::db_delete('appointments', { uuid => $app->{'uuid'} });
}
&embedded_app_deleter({ appt_uuid => $uuid });
my $sources = &subs::db_select('appointments', undef, { source_uuid => $uuid })->hashes;
foreach my $so ( @{$sources} ) {
&embedded_app_deleter({ appt_uuid => $so->{'uuid'} });
&delete_app($so->{'app'},$so->{'uuid'},$so->{'server_time'},'source deletion');
}
&Websocket::send($app, { console => '$(\'.appointment_detail[app="' . $app . '"][uuid="' . $uuid . '"]\').remove();'});
&deletion_registration({ table => 'appointments', app => $app, uuid => $uuid, scope => 'single', server_time => $server_time });
&subs::vacuum($app);
&subs::log_writer('deletion ' . $app . ' ' . $reason);
&budget_runner($app);
}
return { appts => $appts, status => $status };
}
sub is_folder_empty {
my $dirname = shift;
opendir(my $dh, $dirname);# or die "Not a directory";
return scalar(grep { $_ ne "." && $_ ne ".." } readdir($dh)) == 0;
}
sub delete_file($data) {
my $file_uuid = $data->{'file_uuid'};
return unless $data->{'file_uuid'};
my $app_uuid = $data->{'app_uuid'};
my $app = $data->{'app'};
my $appt = &subs::db_select('appointments', undef, { app => $app, uuid => $app_uuid })->hashes->[0];
my $files = eval { return decode_json $appt->{'file'} } || [];
foreach my $file ( grep { $_->{'uuid'} eq $file_uuid } @{$files} ) {
my $filing = $file->{'f'};
my $thumb = $file->{'thumb'};
if ($file->{'att'}) {
my $att_file = &subs::db_select($file->{'att'}, undef, { uuid => $file->{'att_uuid'}, app => $appt->{'app'} })->hashes->[0];
my $atf = eval { return decode_json $att_file->{'file'} } || [];
@{$atf} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$atf};
my $jaf = encode_json $atf;
&subs::db_update($file->{'att'}, { file => $jaf, server_time => &subs::rightNow() }, { uuid => $att_file->{'uuid'}, app => $att_file->{'app'} });
}
if ($file->{'function'} eq 'signatorial') {
my $signatorials = eval { return decode_json &subs::setting_grabber({ app => 'customs', setting => 'signatorials' }) } || [];
@{$signatorials} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$signatorials};
my $jsignatorials = encode_json $signatorials;
&subs::setting_setter({ app => 'customs', setting => 'signatorials', value => $jsignatorials });
}
elsif ($file->{'function'} eq 'receipt') {
my $receipts = eval { return decode_json &subs::setting_grabber({ app => 'budget', setting => 'receipts' }) } || [];
@{$receipts} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$receipts};
my $jreceipts = encode_json $receipts;
&subs::setting_setter({ app => 'budget', setting => 'receipts', value => $jreceipts });
}
elsif ($file->{'function'} eq 'map') {
my $maps = eval { return decode_json &subs::setting_grabber({ app => 'travel', setting => 'maps' }) } || [];
@{$maps} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$maps};
my $jmaps = encode_json $maps;
&subs::setting_setter({ app => 'travel', setting => 'maps', value => $jmaps });
}
elsif ($file->{'function'} eq 'diagram') {
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'handbook', setting => 'diagrams' }) } || [];
@{$diagrams} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$diagrams};
my $jdiagrams = encode_json $diagrams;
&subs::setting_setter({ app => 'handbook', setting => 'diagrams', value => $jdiagrams });
}
elsif ($file->{'function'} eq 'background') {
my $backgrounds = eval { return decode_json &subs::setting_grabber({ app => 'marker', setting => 'backgrounds' }) } || [];
@{$backgrounds} = grep { $_->{'uuid'} ne $file->{'uuid'} } @{$backgrounds};
my $jbackgrounds = encode_json $backgrounds;
&subs::setting_setter({ app => 'marker', setting => 'background', value => $jbackgrounds });
}
if ($thumb && -e $thumb) {
`shred -u $thumb`;
my @folder = split '/', $thumb;
pop @folder;
my $folder = join '/', @folder;
if (&is_folder_empty($folder)) {
rmdir( $folder );
}
}
if (-e $filing) {
my $file = $filing;
`shred -u $file`;
my @folder = split '/', $file;
pop @folder;
my $folder = join '/', @folder;
my $thumb_folder = $folder . '/thumbs';
if (-e $thumb_folder) {
if (&is_folder_empty($thumb_folder)) {
rmdir( $thumb_folder );
}
}
if (&is_folder_empty($folder)) {
rmdir( $folder );
}
}
}
@{$files} = grep { $_->{'uuid'} ne $file_uuid } @{$files};
my $jfiles = encode_json $files;
if (scalar @{$files} == 0 && $data->{'reason'} ne 'delete_app' && grep { $appt->{'type'} eq $_ } qw/image video scan/) {
&delete_app($app,$app_uuid,$appt->{'server_time'},'file deletion');
}
&subs::db_update('appointments', { server_time => &subs::rightNow(), file => $jfiles }, { app => $app, uuid => $app_uuid });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $app_uuid .'\');'});
&deletion_registration({ table => 'appointments', app => $app, uuid => $app_uuid, file_uuid => $file_uuid, scope => 'file', server_time => $appt->{'server_time'} });
}
post '/manager/delete_file' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
&delete_file({ app => $app, file_uuid => $file_uuid, app_uuid => $app_uuid });
$c->render(json => { app => $app, file_uuid => $file_uuid, app_uuid => $app_uuid });
};
sub deletion_registration($data) {
my $app = $data->{'app'};
my $uuid = $data->{'uuid'};
my $scope = $data->{'scope'};
my $table = $data->{'table'};
my $server_time = $data->{'server_time'};
my $remote_machines = &subs::db_select('remote_machines')->hashes;
foreach my $rm ( @{$remote_machines} ) {
my $deletions = eval { return decode_json $rm->{'deletions'} } || [];
push @{$deletions}, { table => $table, app => $app, uuid => $uuid, scope => $scope, initialization => &subs::rightNow(), server_time => $server_time };
my $del = encode_json $deletions;
&subs::db_update('remote_machines', { deletions => $del }, { uuid => $rm->{'uuid'}, ip => $rm->{'ip'}, signatorial => $rm->{'signatorial'} });
}
}
sub deletion_performer($json) {
my $deletions = eval { return decode_json $json } || [];
my $returner = [];
if (scalar @{$deletions} == 0) { return []; }
foreach my $deletion ( @{$deletions} ) {
if ($deletion->{'table'} eq 'appointments') {
if ($deletion->{'scope'} eq 'single') {
&delete_app($deletion->{'app'},$deletion->{'uuid'},$deletion->{'server_time'},'deletion performer single');
}
elsif ( $deletion->{'scope'} eq 'vacuum' ) {
&subs::vacuum_app($deletion->{'app'});
}
elsif ( $deletion->{'scope'} eq 'file' ) {
&delete_file({ app => $deletion->{'app'}, app_uuid => $deletion->{'uuid'}, file_uuid => $deletion->{'file_uuid'} });
}
}
else {
&subs::db_delete($deletion->{'table'}, { uuid => $deletion->{'uuid'}, server_time => $deletion->{'server_time'} });
}
push @{$returner}, $deletion;
}
return $returner;
}
get '/manager/edit_app' => sub($c) {
my $app = $c->param('app');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $select = &subs::db_select('appointments', undef, { app => $app, uuid => $uuid, timestamp => $timestamp })->hashes->[0];
my $s = $c->session('suds');
foreach my $note_type (qw/start_notes notes end_notes/) {
$select->{$note_type} = &subs::note_decrypter($s, $select->{$note_type},$select->{'ost'}) if eval { &subs::note_decrypter($s, $select->{$note_type},$select->{'ost'}) };
}
my $appts = &log_reader({ app => $app, view => 'appointment_display' });
$c->render(template => 'apps/edit_app', app => $select, appts => $appts);
};
post '/manager/edit_app' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
# &subs::cache_delete({ app => $app, context => 'template' });
my $server_time = &subs::rightNow();
my $uuid = $c->param('uuid');
my $app_name = &subs::unformat_name($c->param('app_name'));
my $account = &subs::unformat_name($c->param('account'));
my $project = &subs::unformat_name($c->param('project'));
my $timestamp = $c->param('timestamp');
my $duration = &subs::time_abbrev_translator($c->param('duration'));
my $warranty = $c->param('warranty');
my $movement = $c->param('movement');
my $amount = $c->param('amount');
my $tax = $c->param('tax');
my $aux = $c->param('aux');
my $aux_description = $c->param('aux_description');
my $has_tax = $c->param('has_tax');
my $has_totes = $c->param('has_totes');
my $state = $c->param('state');
my $total = $c->param('total');
my $manufacturer = $c->param('manufacturer');
my $vendor = $c->param('vendor');
my $unit = $c->param('unit');
my $quantity = $c->param('quantity');
my $item = $c->param('item');
my $model = $c->param('model');
my $init = &subs::setting_initializer($app_name,$server_time);
$app_name = $init->{'app'};
my ($start_notes,$notes,$end_notes);
$start_notes = &subs::note_encrypter($c->session('suds'),$c->param('start_notes')) if $c->param('start_notes');
$notes = &subs::note_encrypter($c->session('suds'),$c->param('notes')) if $c->param('notes');
$end_notes = &subs::note_encrypter($c->session('suds'),$c->param('end_notes')) if $c->param('end_notes');
my $seen = 'yes';
if ($timestamp > $server_time) {
$seen = undef;
}
my $data = {
timestamp => $timestamp,
duration => $duration,
warranty => $warranty,
seen => $seen,
app => $app_name,
account => $account,
project => $project,
start_notes => $start_notes,
notes => $notes,
end_notes => $end_notes,
movement => $movement,
amount => $amount,
tax => $tax,
aux => $aux,
aux_description => $aux_description,
total => $total,
manufacturer => $manufacturer,
vendor => $vendor,
unit => $unit,
quantity => $quantity,
item => $item,
model => $model,
has_tax => $has_tax,
has_totes => $has_totes,
'state' => $state,
server_time => $server_time
};
&subs::db_update('appointments', $data,
{
uuid => $uuid,
app => $app
});
my $cv = ¢re_view_grabber({ c => $c, app =>&subs::unformat_name($app), timestamp => $timestamp });
&budget_runner($app);
&padlock_time_extender($c);
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $app . '\',\'' . $uuid .'\');'});
$c->render(text => 'ok');
};
get '/manager/configure/adopt_app' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $timestamp = $c->param('timestamp');
my $scope = $c->param('scope') || 'h';
my $bt = &subs::ago_calc($scope, $timestamp);
my $misc_settings = &misc_setting_list();
my $html;
$c->param('duty' => 'adoption');
foreach my $ms ( keys %{$misc_settings->{$device}} ) {
if ($ms =~ /_location$/) {
my $folder_name = $ms;
$folder_name =~ s/_location$//gi;
my $folder = &subs::home($misc_settings->{$device}->{$ms} . '/' . $app);
my @files = split /\n/, `ls $folder`;
if (scalar @files > 0) {
$html .= '' . &subs::format_name($folder_name) . ':
' . $folder . '
';
foreach my $file ( @files ) {
my $full_file = $folder . '/' . $file;
my $file_q = &subs::db_query('select * from appointments where app = ? and file like ? and file is not null', $app, '%' . $file)->hashes;
if (scalar @{$file_q} == 0) {
$c->param('file' => $full_file);
my $job = &rock_and_roll($c);
if ($file =~ /\.jpg|\.png|\.bmp/) {
my $image = $job->{'image'};
$html .= '
';
}
elsif ($file =~ /\.mpg|\.webm|\.mp4/) {
$c->param('file' => $full_file);
my $job = &rock_and_roll($c);
my $image = $job->{'image'};
$html .= '';
}
}
}
}
}
}
$html .= '
';
$c->render('text' => $html);
};
post '/manager/configure/adopt_app_confirm' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $files = $c->param('files');
my $timestamp = $c->param('timestamp');
$files = eval {return decode_json $files } || [];
my $push_files = [];
my $upload_type;
foreach my $file ( @{$files} ) {
my ($destination,$asset,$type) = &subs::file_device_renamer({ file => $file->{'file'}, app => $app, type => $file->{'type'}, is_thumb => 1 });
my $data = { server_time => $file->{'timestamp'}, f => $file->{'file'}, uuid => &subs::random_string_creator(8), type => $file->{'type'}, thumb => $destination . $asset };
$data = &thumbnail_creator($data);
push @{$push_files}, $data;
$upload_type = $file->{'type'};
}
my $jfiles = encode_json $push_files;
&appointment_writer($c,{
app => $app,
file => $jfiles,
timestamp => $timestamp,
type => $upload_type
});
$c->render('text' => 'ok');
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
};
get '/manager/clothesline' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $project = &subs::unformat_name($c->param('project'));
my $account = &subs::unformat_name($c->param('account'));
my $time_plinkos = &clothesline_calculator($app);
my $cl = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'clothesline' })} || {};
my $html = $c->render_to_string(template => 'apps/clothesline', app => $app, cl => $cl , time_plinkos => $time_plinkos );
&subs::hang_to_dry();
$c->render(json => { html => $html});
};
post '/manager/clothesline' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $setting = $c->param('setting');
my $value = $c->param('value');
if ($c->param('is_json')) {
$value = eval { return decode_json $value } || [];
}
my $cl = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'clothesline' })} || {};
$cl->{$setting} = $value;
my $jcl = encode_json $cl;
&subs::setting_setter({ app => $app, setting => 'clothesline', value => $jcl });
&subs::hang_to_dry();
$c->render(json => $cl);
};
sub clothesline_calculator($app) {
my $appts = &subs::db_select('appointments', undef, { app => $app })->hashes;
my $time_plinkos = clone $gb::time_plinkos;
foreach my $appt ( @{$appts} ) {
my $time = localtime($appt->{'timestamp'} / 1000);
for (my $n = 0; $n <= 8; $n++) {
my $ft = $time->[$n];
if ($n == 2) {
if ($ft == 0) {
$ft = '12am';
}
elsif ($ft >= 12) {
if ($ft == 12) { $ft = 24; }
$ft = ($ft - 12) . 'pm';
}
elsif ($time->[$n] > 0 && $time->[$n] < 13) {
$ft .= 'am';
}
}
if ($n == 4) { $ft = $time->monname; }
if ($n == 5) { $ft += 1900; }
if ($n == 6) { $ft = $time->wdayname; }
push @{$time_plinkos->[$n]->{'clothes'}}, { formatted => $ft, value => $time->[$n] };
}
}
foreach my $tp ( @{$time_plinkos} ) {
foreach my $cl ( @{$tp->{'clothes'}} ) {
my @seen = grep { $_->{'formatted'} eq $cl->{'formatted'} } @{$tp->{'clothes'}};
if (scalar @seen >= 2) {
$tp->{'reoccuring'}->{$cl->{'formatted'}} = [] unless $tp->{'reoccuring'}->{$cl->{'formatted'}};
push @{$tp->{'reoccuring'}->{$cl->{'formatted'}}}, $cl;
}
}
}
&subs::hang_to_dry();
return $time_plinkos;
}
get '/manager/volume_control' => sub($c) {
my $return_volume = '[]';
my $stream = $c->param('stream');
my $volume = $c->param('volume');
my $max = $c->param('max');
my $card = $c->param('device');
my $remote_machines = &subs::db_select('remote_machines', undef, { connection => 'active' })->hashes;
my ($json_vol,$md);
if ($card && lc $card ne 'local' && grep { $_->{'uuid'} eq $card } @{$remote_machines}) {
$c->param('device', 'local');
$c->param('remote_uuid', $card);
my $jdata = &remote_relay_request($c);
my $data = eval { return decode_json $jdata } || {};
$json_vol = $data->{'volumes'};
$md = eval { return decode_json $data->{'md'} } || {};
}
else {
if ($stream && $volume) {
if ($device eq 'mobile') {
$stream = lc $stream;
`termux-volume $stream $volume`;
}
else {
`amixer set $stream $volume%`;
}
}
if ($device eq 'mobile') {
$return_volume = `termux-volume`;
}
else {
foreach my $control ( qw/Master Capture/ ) {
my $amixer = `amixer get $control`;
my @lines = split /\n/, $amixer;
my $volume;
foreach my $l ( @lines ) {
if ($l =~ /Left:/gi) {
my @p = split ' ', $l;
my $p = $p[-2];
$p =~ s/[^0-9]//gi;
$volume = $p;
}
}
push @{$json_vol}, { stream => $control, volume => $volume, max_volume => 100 };
}
}
if ($device eq 'mobile') {
$json_vol = decode_json $return_volume;
}
foreach my $j ( @{$json_vol} ) {
$j->{'stream'} = &subs::format_name($j->{'stream'});
}
my $ws_watcher = &subs::home('~/.president/ws_watcher');
$md = eval { return decode_json read_file($ws_watcher) } || {};
}
$c->render( json => { volumes => $json_vol, remote_machines => $remote_machines, md => $md });
};
post '/manager/clothesline' => sub($c) {
my $app = $c->param('app');
my $setting = $c->param('setting');
my $value = $c->param('value');
my $timestamp = $c->param('timestamp');
my $cl = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'clothesline' })} || {};
$c->render(json => $cl);
};
post '/manager/calculate' => sub($c) {
my $formula = $c->param('formula');
my ($evaluation,$uom,$format);
($formula,$evaluation,$uom,$format) = &formula_calculator($formula);
$c->render(json => { format => $format, formula => $formula, evaluation => $evaluation, uom => $uom });
};
sub formula_calculator($formula) {
my @formula = split / /, $formula;
my ($evaluation,$uom,$format);
my $formulas = [];
if ($formula =~ /[a-zA-Z]/) {
for (my $n = 0; $n <= scalar @formula; $n++ ) {
if ($formula[$n] eq 'to') {
my $pre = $formula[$n - 1];
my $pre_unit = $pre;
my $pre_number = $pre;
$pre_number =~ s/[A-Za-z]//gi;
$pre_unit =~ s/[0-9.-]//gi;
my $post = $formula[$n + 1];
my $post_number = $post;
my $post_unit = $post;
$post_number =~ s/[A-Za-z]//gi;
$post_unit =~ s/[0-9.-]//gi;
my $post_measure = $gb::measures->{$post_unit};
unless ($post_measure) {
foreach my $pu ( ( lc $post_unit, uc $post_unit ) ) {
$post_measure = $gb::measures->{$pu};
if ($post_measure->{'name'}) { last; }
}
}
foreach my $for ( @{$gb::measures->{$pre_unit}->{'formulas'}} ) {
if ($for =~ /\Q$post_unit/gi) {
$for =~ s/x/\Q$pre_number/gi;
$for =~ s/\Q$post_unit//gi;
$for =~ s/\\//gi;
push @{$formulas}, $for;
$evaluation = eval $for;
last if $post_unit eq $post;
if ($gb::measures->{$post_unit}->{'format'}) {
$format = $gb::measures->{$post_unit}->{'format'};
}
else {
$format = '0.000';
}
$uom = $post_unit;
}
}
# foreach my $for ( @{$gb::measures->{$post_unit}->{'formulas'}} ) {
# if ($for =~ /\Q$pre_unit/gi) {
# $for =~ s/x/\Q$pre_number/gi;
# $for =~ s/\Q$pre_unit//gi;
# $for =~ s/\\//gi;
# push @{$formulas}, $for;
# $evaluation = eval { $for };
# if ($gb::measures->{$post_unit}->{'format'}) {
# $format = $gb::measures->{$post_unit}->{'format'};
# }
# else {
# $format = '0.000';
# }
# $uom = $post_unit;
# }
# }
}
}
}
else {
$evaluation = eval $formula;
}
return ($formula,$evaluation,$uom,$format);
}
post '/manager/keyboard' => sub($c) {
my $kb = &keyboard_maker($c);
$c->render(text => $kb);
};
sub keyboard_maker($c) {
my $timestamp = $c->param('timestamp');
my $browser_tab_id = $c->param('browser_tab_id');
my $toggle = $c->param('toggle');
my $accts = [];
my $projs = [];
my $accounts = &subs::db_query("select * from settings where setting = ? and value=?",'pos','account');
my $acc = $accounts->hashes;
my $keys = {};
if ($toggle eq 'keyboard' || $toggle eq 'calculator') {
foreach my $key (@{$gb::inputs}) {
$keys->{$key->{'c'}} = &subs::random_string_creator();
}
foreach my $key (keys %{$gb::measures}) {
$keys->{$key} = encode_json $key;
}
my $key_cutter = &subs::encrypter($c->session('suds'), encode_json($keys));
&subs::setting_setter({ app => 'keyboard', setting => $toggle, value => $key_cutter, timestamp => $timestamp, browser_tab_id => $browser_tab_id });
}
if ($toggle eq 'delorean') {
foreach my $a ( reverse @{$acc} ) {
push @{$accts},$a unless grep { $_->{'app'} eq $a->{'app'}} @{$accts};
$a->{'formatted_name'} = &subs::format_name($a->{'app'});
}
my $projects = &subs::db_query("select * from settings where setting = ? and value=?",'pos','project');
my $proj = $projects->hashes;
foreach my $a ( reverse @{$proj} ) {
push @{$projs},$a unless grep { $_->{'app'} eq $a->{'app'}} @{$projs};
$a->{'formatted_name'} = &subs::format_name($a->{'app'});
}
}
my ($av_data);
if ($c->param('avData') && $toggle eq 'walkboy') {
$av_data = decode_json($c->param('avData'));
foreach my $av (@{$av_data}) {
if ($av->{'kind'} eq 'audioinput') {
$av->{'icon'} = 'microphone';
}
elsif ($av->{'kind'} eq 'videoinput') {
if ($av->{'label'} =~ /front/gi) {
$av->{'icon'} = 'camera front';
}
else {
$av->{'icon'} = 'camera back';
}
}
elsif ($av->{'kind'} eq 'audiooutput') {
$av->{'icon'} = 'speaker';
}
}
}
my $websockets;
if ($toggle eq 'console' || $toggle eq 'controller') {
my $web_query = &subs::db_query('select * from websockets where browser_tab_id = ?',$browser_tab_id);
$websockets = $web_query->hashes;
}
my $notifications;
if ($toggle eq 'notifications') {
$notifications = ¬ification_grabber({});
};
my $config = &subs::config_reader();
my $remote_connect = $gb::ws;
my $kb = $c->render_to_string(
browser_tab_id => $browser_tab_id,
accounts => $accts,
projects => $projs,
template => 'keyboard',
'keys' => $keys,
toggle => $toggle,
device => $device,
av_data => $av_data,
websockets => $websockets,
notifications => $notifications,
config => $config,
manager_file => &manager_file_maker($c->session('name')),
pseudonyms => &pseudonym_maker('viewer', ''),
measures => $gb::measures,
ws => $gb::ws,
);
return $kb;
}
sub manager_file_maker($session_name) {
my ($my_name,$computer_name,$hostname,$hostnamer,$database_name);
my ($db,$database) = &subs::database_grabber();
$hostname = `hostname`;
chomp $hostname;
$hostnamer = eval { return &subs::db_select('devices', ['name'], { hostname => $hostname } )->hash->{name} };
$my_name = $session_name || &subs::setting_grabber({ app => 'me', setting => 'my_name' });
$computer_name = &subs::setting_grabber({ app => 'me', setting => 'computer_name' });
$database_name = $database;
$database_name =~ s/^database\///;
$database_name =~ s/.db$//gi;
my @database_name = split '/', $database_name;
$database_name = $database_name[-1];
return ($my_name || $hostnamer || $hostname) . '@' . $database_name . '.' . ($computer_name || $hostname);
};
get '/manager/keyboard_alias' => sub($c) {
my $key = $c->param('key');
my $toggle = $c->param('toggle');
my $browser_tab_id = $c->param('browser_tab_id');
my $value = &subs::db_select('settings', ['value','timestamp'], { app => 'keyboard', setting => $toggle, browser_tab_id => $browser_tab_id })->hash;
my $key_cutter = &subs::decrypter($c->session('suds'),$value->{'value'});
$key_cutter = decode_json $key_cutter;
foreach my $k (keys %{$key_cutter}) {
if ($key_cutter->{$k} eq $key) {
$key = $k;
}
}
my $path = './public/icons/lettering/' . $key . '.png';
if (! -e $path) {
$path = './public/icons/lymeboard' . $key . '.png';
if (! -e $path) {
my @b = grep { $_->{'c'} eq $key } @{$gb::inputs};
if ($b[0]->{'img'}) {
$path = './public/icons/lymeboard/' . lc $b[0]->{'img'} . '.png';
}
}
}
my $paths = Mojo::File->new($path);
$c->render_file('filepath' => $paths->to_string);
};
post '/manager/keyboard_presser' => sub($c) {
my $key = $c->param('key');
my $toggle = $c->param('toggle');
my $shift = $c->param('shift');
my $ctrl = $c->param('ctrl');
my $fn = $c->param('fn');
my $timestamp = $c->param('timestamp');
my $destination = $c->param('destination');
my $browser_tab_id = $c->param('browser_tab_id');
my $value = &subs::db_select('settings', ['value','timestamp'], { app => 'keyboard', setting => $toggle, browser_tab_id => $browser_tab_id })->hash;
my $key_cutter = &subs::decrypter($c->session('suds'),$value->{'value'});
$key_cutter = decode_json $key_cutter;
foreach my $k (keys %{$key_cutter}) {
if ($key_cutter->{$k} eq $key) {
$key = $k;
$key = uc $key if $shift eq 'yes';
}
}
&Websocket::send('server', { key => $key, origin => $browser_tab_id, destination => $destination, toggle => $toggle, timestamp => $timestamp });
$c->render(json => { key => $key });
};
get '/manager/say_it' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $words = $c->param('words');
&subs::say_it($words);
$c->render(text => 'said ' . $words);
&Websocket::send('server', { json => { type => 'command', command => 'say_it', params => $words, timestamp => $timestamp } });
};
sub lock_screen($c) {
if ($c) {
my $authentication = $c->session('authentication');
if (-e $database && $device eq 'mobile') {
}
}
}
sub unlock_screen($c) {
my $authentication = $c->session('authentication');
if (-e $database && $device eq 'mobile') {
my $finger = `termux-fingerprint`;
if (my $fingerprint = eval { return decode_json $finger }) {
if ($fingerprint->{'auth_result'} eq 'AUTH_RESULT_SUCCESS') {
$c->session('authentication' => 'approved');
}
else {
$c->session('authentication' => 'rejected');
}
}
}
}
sub notification_sender($m,$db) {
my $origin = &subs::format_name(&subs::setting_grabber({ app => 'me', setting => 'computer_name' })) ||&subs::shorthand_name(`hostname`);
my $message = $m->{'message'};
my ($db,$database,$sql) = &subs::database_grabber();
my $app = &subs::unformat_name($m->{'app'} || '');
$m->{'settings'} = &subs::settings_grabber({ app => $app, settings => [
'start_notification_text', 'stop_notification_text', 'budget_notification_text', 'notification_text',
'start_notification_sound', 'stop_notification_sound', 'budget_notification_sound', 'notification_sound'
] }) unless $m->{'settings'};
my $title = ($origin) . ': ' . $m->{'title'};
$m->{'timestamp'} = &subs::rightNow();
my $sound = $m->{'sound'} || 'ding.mp3';
my $sound_file = $m->{'settings'}->{$m->{'type'} . '_notification_sound'} || './public/sounds/notifications/' . $sound;
my $words = $m->{'words'} || $m->{'message'} || $m->{'settings'}->{$m->{'type'} ? $m->{'type'} . '_notification_text' : 'notification_text'};
if ($m->{'synth'}) {
Mojo::IOLoop->subprocess->run_p(sub {
&subs::run_command($m->{'synth'} . ' &');
if ($m->{'words'}) {
&subs::say_it($m->{'words'});
}
});
}
else {
Mojo::IOLoop->subprocess->run_p(sub {
if ($sound) {
my $co = 'play -q ' . $sound_file;
`$co`;
}
if ($words) {
&subs::say_it($words);
}
});
}
my $image;
my $pwd = `pwd`;
chomp $pwd;
if ($m->{'image'}) {
$image = $pwd . '/public' . $m->{'image'};
}
else {
$image = &subs::setting_grabber({ app => &subs::unformat_name($m->{'title'}), setting => 'main_image' });
unless (-e $image) {
$image = $pwd . '/public/images/jonathans/logo red yellow.png';
}
}
$image =~ s/ /\\ /gi;
if ($device eq 'mobile') {
my $id = &subs::random_string_creator();
my $url = 'https://127.0.0.1:' . $ENV{PORT_AHOY} . '/manager?app=' . $m->{'app'} . '×tamp=' . $m->{'timestamp'};
`echo "$message" | termux-notification -i $id -t "$title" --vibrate "200,150,200,150" --image-path $image`;# --action termux-open "$url"`;# --on-delete "$pwd/scripts/app_displayer.pl '$app' close"`;
}
elsif ( eval { $sql->db } && $sql->dsn !~ /:$/) {
my $c = app->build_controller;
my $content = $c->render_to_string(
n => $m,
template => 'notification',
);
if ($m->{'role'} != 0) {
&Websocket::send('server', {
app => $m->{'app'},
type => 'notification',
title => $m->{'title'},
role => $m->{'role'} || 'guest',
message => $m->{'message'},
icon => $m->{'image'},
timestamp => $m->{'timestamp'},
html => $content
});
}
}
foreach my $embedded (qw/ watch teletype /) {
my $watch = &subs::device_lister($m->{'timestamp'},$embedded);
if (eval {$watch->{'ip'}}) {
my $ping = 'timeout .2 ping -c 1 ' . $watch->{'ip'};
my $ping_test = `$ping`;
if ($ping_test =~ /ttl/gi) {
my $ua = Mojo::UserAgent->new();
$ua->connect_timeout(1);
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/notification?title=' . $title .
'¬ification=' . $message . '&sound=/' . $sound . '&sound_file=' . $sound_file;
Mojo::IOLoop->subprocess->run_p(sub {
my $res = eval { return $ua->insecure(1)->get($watch_home)->result };
});
}
}
}
if (eval { $sql->db } && $sql->dsn !~ /:$/) {
my $db = $sql->db;
&subs::db_insert('notifications', {
app => $m->{'app'},
role => $m->{'role'} || 3,
title => $m->{'title'},
image => $m->{'image'},
message => $m->{'message'},
timestamp => $m->{'timestamp'},
uuid => $m->{'uuid'} || &subs::random_string_creator(20)
});
}
}
sub authentication_passer($c) {
my $server_time = &subs::rightNow();
my $authentication = $c->session('authentication') || 'revoked';
if ($c->session('authentication') eq 'denial' || $c->session('reject_count') > 3 || ($c->stash('no') && $c->stash('no') == 1)) {
my $denial = $c->render(template => 'guest_layouts/denial', message => '... and fuck you too!');
$c->session('authentication' => 'fuck you');
$authentication = 'denial';
$c->rendered;
return;
}
elsif ($authentication eq 'approved' && $c->session('server_time') > $server_time + 5000) {
return $authentication;
}
$c->session('server_time' => $server_time);
my $suds = $c->session('suds');
my $dob = $c->session('database');
my $name = $c->param('name');
my $warranty = $c->session('warranty');
my $visitor = $c->tx->local_address eq $c->tx->remote_address ? 'Me' : ($c->param('manager_file') || $c->tx->remote_address);
my $string = $c->tx->req->url->to_string;
unless ($c->stash('browser_tab_id') && ($authentication eq 'approved' || $authentication eq 'revoked')) {
&subs::say_it($visitor);
my ($db,$database) = &subs::database_grabber();
if ($db) {
my $time = &subs::rightNow();
my $warranty = &subs::ago_calc(&subs::setting_grabber({ app => 'customs', setting => 'warranty' }) || '-10d', $time);
my $data = { warranty => $warranty, uuid => &subs::random_string_creator(40), app => 'customs', timestamp => $time, server_time => $time, type => 'dingaling', data => $visitor };
# my $insert = &subs::db_insert('appointments', $data );
}
¬ification_sender({ app => 'customs', role => 'citizen', type => 'authentication', title => 'Dingaling', message => $visitor . ' ' . $string, image => "/images/make believe/lock.png" },$dob);
}
if (! -e $dob) {
$authentication = "revoked";
}
else {
my ($db,$database,$sql) = &subs::database_grabber();
my $hardness;
$hardness = &subs::decrypter($suds,&subs::db_select('security', ['credential'], { level => 1 })->hash->{credential});
unless (secure_compare $hardness, $suds) {
$authentication = 'revoked';
}
my $activity_timeout = &subs::setting_grabber({ app => 'me', setting => 'activity_timeout' }) || '2h';
$activity_timeout = &subs::time_abbrev_translator($activity_timeout);
my $padlock_time = &subs::decrypter($c->session('suds'), &subs::setting_grabber({ app => '__president', setting => 'pl_time' }) ) || 0;
$c->stash('pl_time' => $padlock_time);
if ($c->session('authentication') eq 'approved' && $server_time > $padlock_time) {
&lock_session($c);
}
elsif ($c->session('source') eq 'ticket' && $c->session('authentication') eq 'approved') {
my $tick = &subs::db_query('select * from tickets where uuid=?', $c->session('ticket_uuid') );
my $ticket = $tick->hashes->[0];
$c->stash('debriefer' => $ticket->{'debriefer'});
if ($c->session('server_time') < $ticket->{'server_time'}) {
my $secretive = $ticket->{'secret'};
my $ver = url_unescape `echo "$secretive" | base64 --decode`;
my $ts = &subs::note_decrypter($ticket->{'password'},$ver);
my $sj = decode_json $ts;
my $suds = &subs::note_decrypter($sj->{'p'}, $ticket->{'suds'});
chomp $suds;
$c->session('suds' => $suds);
$c->session('server_time' => $server_time);
$authentication = 'approved';
}
if ($ticket->{'warranty'} <= $server_time || $ticket->{'status'} ne 'active') {
$authentication = 'revoked';
}
else {
$c->session('warranty' => $ticket->{'warranty'});
}
}
elsif ($c->session('warranty') < $server_time) {
$authentication = 'revoked';
}
}
unless ($authentication eq 'approved') {
$c->session('authentication' => 'revoked');
$c->session('bti', $c->stash('browser_tab_id'));
my $restore_list = [];
$c->session('database' => undef);
$c->session('suds' => undef);
unless (-e $database) {
if ($c->param('restore_list')) {
my $list = $c->param('restore_list');
$restore_list = &subs::restore_list($list);
@{$restore_list} = grep { $_->{'filename'} =~ /enc$/gi } @{$restore_list};
}
}
my $start_dir = $config->{'start_dir'};
if ($c->param('neighbour')) {
$c->render(json => { purpose => $device, 'restore_list' => $restore_list });
}
else {
$c->render(
template => 'gate',
layout => 'gate',
restore_list => $restore_list,
start_dir => $start_dir,
config => { 'gate' => {'background_colour' => $config->{'gate'}->{'background_colour'} } },
);
}
}
return $authentication;
}
post '/manager/configure/password_update' => sub($c) {
my $timestamp = $c->param('timestamp');
my $server_time = &subs::rightNow();
my ($db,$database,$sql) = &subs::database_grabber();
$c->param('reason' => 'password_update');
&subs::backup_now($c);
my $numerics = &password_maker($c);
if ($numerics eq 'noway') {
$c->render(json => { result => 'ok' });
$c->rendered;
return;
}
my $secret = &subs::decrypter($c->session('suds'),&subs::db_select('security', ['credential'], { level => 1 })->hash->{credential});
my $credential = &subs::encrypter($numerics,$numerics);
my $cred_hunt = &subs::db_select('security', ['credential','level','server_time','timestamp'], { });
my $creds = $cred_hunt->hashes;
@{$creds} = grep { $_->{'level'} ne 'padlock' } @{$creds};
if (secure_compare $c->session('suds'), $secret) {
foreach my $cr ( @{$creds} ) {
my $credjawntial = &subs::decrypter($secret,$cr->{'credential'});
my $newjawntial = &subs::encrypter($numerics,$credjawntial);
my $level = 2;
if ($level eq 'padlock') {
$level = 'padlock';
}
&subs::db_update('security', { level => $level, credential => $newjawntial }, { timestamp => $cr->{'timestamp'}, server_time => $cr->{'server_time'} });
}
&subs::db_insert('security', { level => 1, database => $database, credential => $credential, timestamp => $timestamp, server_time => $server_time, uuid => &subs::random_string_creator(30) });
$c->session('suds' => $numerics);
&subs::db_delete('security', { level => 'padlock' });
&subs::db_delete('settings', { app => '__president', setting => 'pl_time' });
&subs::db_delete('settings', { app => '__president', setting => 'padlock_pulls' });
$c->render(json => { result => 'ok' });
&subs::say_it('Password has been updated');
}
else {
&subs::say_it('no dice mister!');
$c->render(json => { result => 'fail' });
}
};
post '/manager/embedded/tauthorization' => sub ($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $tauthorization = $c->param('tauthorization');
my $chip_id = $c->param('chip_id');
my $patience = &subs::random_string_creator(25);
&subs::setting_setter({ app => $edt, setting => 'patience', value => $patience, timestamp => $timestamp });
my $auth = &subs::note_encrypter($patience,$tauthorization);
$tauthorization = `(echo $auth) | base64 -w 0`;
my $set = &subs::setting_setter({ app => $edt, setting => 'tauthorization', value => $tauthorization });
$c->render(json => { settings => $set });
};
post '/manager/teletype/enable_tty' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $enabled = $c->param('enabled');
my $chip_id = $c->param('chip_id');
my $saved_enabled = &subs::setting_grabber({ app => $edt, setting => 'enabled', subsetting => $chip_id });
if ($saved_enabled == 1) {
$saved_enabled = 0;
}
else {
$saved_enabled = 1;
}
my $set = &subs::setting_setter({ app => $edt, setting => 'enabled', value => $saved_enabled, timstamp => $timestamp, subsetting => $chip_id });
$c->render(json => { enabled => $saved_enabled });
};
get '/manager/teletype/wifi_update' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $chip_id = $c->param('chip_id');
my $json_wifi = &subs::setting_grabber({ app => $edt, setting => 'wifi', subsetting => $chip_id }) || '{}';
my $wifi = decode_json $json_wifi;
$c->render(text => $json_wifi);
};
post '/manager/teletype/appearance' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $field = $c->param('field');
my $value = $c->param('value');
my $chip_id = $c->param('chip_id');
my $op_d = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $op = eval { return decode_json $op_d } || {};
if ($field =~ /colour/gi) {
my $colour = $value;
$colour =~ s/^#//gi;
my @rgb = map $_ , unpack 'C*', pack 'H*', $colour;
$op->{'__specs'}->{$field . '_rgb'} = \@rgb;
}
$op->{'__specs'}->{$field} = $value;
delete $op->{$field};
$op_d = encode_json $op;
my $done = &subs::setting_setter({ app => $edt, setting => 'operator_door', value => $op_d, subsetting => $chip_id });
$c->render(json => $done);
};
post '/manager/teletype/wifi_config' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $field = $c->param('field');
my $value = $c->param('val');
my $chip_id = $c->param('chip_id');
my $json_wifi = &subs::setting_grabber({ app => $edt, setting => 'wifi', subsetting => $chip_id }) || '{}';
my $wifi = decode_json $json_wifi;
$wifi->{$field} = $value;
$json_wifi = encode_json $wifi;
my $returner = &subs::setting_setter({ app => $edt, setting => 'wifi', value => $json_wifi, subsetting => $chip_id });
my $teletype = &subs::device_lister($timestamp, $edt);
$c->render(json => $returner);
};
post '/manager/teletype/wifi_update' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $chip_id = $c->param('chip_id');
my $teletype = &subs::device_lister($timestamp, $edt, undef, $chip_id);
my $wifi_url = 'http://' . $teletype->{'ip'} . ':' . $config->{'port'} . '/wifi_update';
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($wifi_url)->result;
$c->render(text => $res->body);
};
post '/manager/embedded/now_me' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $ip = $c->param('ip');
my $chip_id = $c->param('chip_id');
my $name = &subs::format_name($c->param('name'));
my $res = &now_me({ timestamp => $timestamp, edt => $edt, ip => $ip, name => $name, chip_id => $chip_id, browser_tab_id => $c->param('browser_tab_id') });
$c->render('text' => $res);
};
get '/teletype/neighbours' => sub($c) {
my $timestamp = $c->param('timestamp');
my $devices = &subs::device_lister($timestamp, '');
$c->render(json => $devices);
};
get '/manager/embedded' => sub($c) {
my $timestamp = $c->param('timestamp');
my $returner = &embedded_grabber($c,$timestamp);
$returner->{'html'} = &window_maker({ user_agent => $c->param('user_agent'), app => 'Embedded', timestamp => $timestamp, contents => $returner->{'contents'} }, $timestamp);
$c->render(json => $returner);
};
sub embedded_grabber($c,$timestamp) {
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $view = $c->param('view') || 'everything';
my $embedded = &subs::device_lister($timestamp,$edt,undef,$chip_id);
$timestamp = $c->param('timestamp');
my $tty_enabled = &subs::setting_grabber({ app => $edt, setting => 'enabled' });
my $pseudonyms = &pseudonym_maker($edt, '');
my $json_wifi = &subs::setting_grabber({ app => $edt, setting => 'wifi', subsetting => $chip_id }) || '{}';
my $wifi = decode_json $json_wifi;
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id } );
my $op_d = eval { return decode_json $od } || {};
my $room_count = &subs::setting_grabber({'app' => 'me', setting => 'room_count', subsetting => $chip_id }) || $op_d->{'__specs'}->{'room_count'} || 2;
$op_d->{'__specs'}->{'room_count'} = $room_count;
my $room_max = 2;
my $components = $gb::embedded_components;
my $start_n = 0;
if ($edt eq 'teletype') {
$room_max = 8;
$start_n = 1;
$components = { 'button' => $gb::embedded_components->{'button'} };
}
elsif ($edt eq 'watch') {
$room_max = 6;
$start_n = 1;
$components = { 'button' => $gb::embedded_components->{'button'} };
}
else {
$room_count = 1;
$room_max = 28;
}
my $embedded_scope = &subs::setting_grabber({ app => $edt, setting => 'watch_scope', subsetting => $chip_id });
my $settings;
my $syl_count = 10;
$syl_count = 1 unless $edt eq 'microcontroller';
foreach my $component ( keys %{$components} ) {
my $syl = &subs::shorthand_name($component, $syl_count);
for (my $n = $start_n; $n <= $room_count * $room_max; $n++) {
my $app = $op_d->{$syl . $n}->{'app'} || '';
my $mov = $op_d->{$syl . $n}->{'movement'} || 'command';
my $aset = &subs::settings_grabber({ app => $app });
my $toggle = $aset->{'toggle' } eq 'on' ? 1 : 0;
my $tog = !$toggle || $toggle eq 'off' ? 1 : 0;
$aset->{'measures'} = eval { return decode_json $aset->{'app_measures'} } || {};
$settings->{$syl . $n} = {
app => $app,
toggle => $tog,
formatted_name => &subs::format_name($app),
movement => $mov,
inverted => $op_d->{$syl . $n}->{'inverted'},
toggle => $toggle,
settings => $aset,
direction => $components->{$component}->{'direction'},
measure => $op_d->{$syl . $n}->{'measure'},
threshold => $op_d->{$syl . $n}->{'threshold'},
name => $op_d->{$syl . $n}->{'name'}
};
}
}
my $movements = {};
foreach my $m ( qw/usual command kill record start toggle measure/ ) {
$movements->{$m} = {
formatted_name => &subs::format_name($m),
mov => $m
};
}
my $tauthorization = &subs::setting_grabber({ app => $edt, setting => 'tauthorization' });
my @embedded_ports;
if ($device eq 'computer' || $device eq 'server') {
my $embedded_ports = `ls /dev/ttyACM*`;
@embedded_ports = split /\n/, $embedded_ports;
}
my $chip_ids = [];
foreach my $chip ( @{&subs::db_select('devices')->hashes}) {
$chip->{'chip_ids'} = eval { return decode_json $chip->{'chip_ids'} } || [{}];
push @{$chip_ids}, @{$chip->{'chip_ids'}};
}
my $returner = {
template => 'embedded/embedded',
embedded => $embedded,
embedded_ports => \@embedded_ports,
window_maker => 'yes',
settings => $settings,
movements => $movements,
room_count => $room_count,
room_max => $room_max,
embedded_scope => $embedded_scope,
tauthorization => $tauthorization,
tty_enabled => $tty_enabled,
pseudonyms => $pseudonyms,
wifi => $wifi,
operator_door => $op_d,
device_type => $edt,
components => $components,
chip_ids => $chip_ids,
chip_id => $chip_id,
edt => $edt,
start_n => $start_n,
view => $view
};
$returner->{'contents'} = $c->render_to_string(
%{$returner}
);
return $returner;
}
get '/manager/embedded/pin_grabber' => sub($c) {
my $edt = $c->param('edt');
my $numero = $c->param('numero');
my $pin = $c->param('pin') || $numero;
my $form = $c->param('form');
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp');
my $returner = &embedded_pin_grabber({
edt => $edt,
numero => $numero,
pin => $pin,
form => $form,
chip_id => $chip_id,
timestamp => $timestamp
});
$c->render(json => $returner);
};
sub embedded_pin_grabber($data) {
my $timestamp = $data->{'timestamp'} || &subs::rightNow();
my $chip_id = $data->{'chip_id'};
my $form = $data->{'form'};
my $numero = $data->{'numero'};
my $pin = $data->{'pin'} || $data->{'numero'};
my $edt = $data->{'edt'};
my $device_type = $data->{'edt'};
my $current_component = $data->{'component'};
my $embedded = &subs::device_lister($timestamp,$edt,undef,$chip_id);
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id } );
my $op_d = eval { return decode_json $od } || {};
my $returner;
my $components = $gb::embedded_components;
my $settings;
my $movements;
foreach my $m ( qw/usual command kill record start toggle measure/ ) {
$movements->{$m} = {
formatted_name => &subs::format_name($m),
mov => $m
};
}
my $syl_count = 10;
$syl_count = 1 unless $edt eq 'microcontroller';
foreach my $component ( keys %{$components} ) {
if ($current_component && $current_component ne $component) {
next;
}
my $syl = &subs::shorthand_name($component, $syl_count);
my $n = $numero;
my $app = $op_d->{$syl . $n}->{'app'} || '';
my $mov = $op_d->{$syl . $n}->{'movement'} || 'command';
my $aset = &subs::settings_grabber({ app => $app });
my $toggle = $aset->{'toggle' } eq 'on' ? 1 : 0;
my $tog = !$toggle || $toggle eq 'off' ? 1 : 0;
$aset->{'measures'} = eval { return decode_json $aset->{'app_measures'} } || {};
$settings->{$syl . $n} = {
app => $app,
toggle => $tog,
formatted_name => &subs::format_name($app),
movement => $mov,
inverted => $op_d->{$syl . $n}->{'inverted'},
toggle => $toggle,
settings => $aset,
direction => $components->{$component}->{'direction'},
measure => $op_d->{$syl . $n}->{'measure'},
threshold => $op_d->{$syl . $n}->{'threshold'},
name => $op_d->{$syl . $n}->{'name'}
};
my $c = app->build_controller;
$returner->{'html'} .= $c->render_to_string(
template => 'embedded/component',
n => $numero,
component => $component,
settings => $settings,
components => $components,
embedded => $embedded,
movements => $movements,
device_type => $device_type,
source => 'grabber',
pin => $pin,
name => $op_d->{$syl . $n}->{'name'}
);
}
my @embedded_ports;
if ($device eq 'computer' || $device eq 'server') {
my $embedded_ports = `ls /dev/ttyACM*`;
@embedded_ports = split /\n/, $embedded_ports;
}
my $chip_ids = [];
foreach my $chip ( @{&subs::db_select('devices')->hashes}) {
$chip->{'chip_ids'} = eval { return decode_json $chip->{'chip_ids'} } || [{}];
push @{$chip_ids}, @{$chip->{'chip_ids'}};
}
return $returner;
};
get '/manager/embedded/wigi' => sub($c) {
my $ip = $c->param('ip');
my $timestamp = $c->param('timestamp');
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $watch = &subs::device_lister($timestamp, $edt, undef, $chip_id);
if ($watch->{'ip'}) {
my $wat_set = &subs::setting_grabber({ app => $edt, setting => 'operator_door', device => $device, subsetting => $chip_id });
my $watch_settings = eval { return decode_json $wat_set } || {};
my $auth = $watch_settings->{'__specs'}->{'authorization'};
my $author = `echo $auth | base64 --decode`;
my $authorization = &subs::note_decrypter($watch_settings->{'__shutup'}->{'patience'}, $author);
my $wigi_url = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/wigi?timestamp=' . $timestamp . '&authorization=' . $auth;
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($wigi_url)->result;
my $wigi = eval { return decode_json $res->body } || {};
my $rauth = $wigi->{'authorization'};
my $rauthorization = `echo $rauth | base64 --decode`;
my $remote_auth = &subs::note_decrypter($watch_settings->{'__shutup'}->{'patience'}, $rauthorization);
if (secure_compare($remote_auth, $authorization)) {
my $buttons = $wigi->{'buttons'};
my $measures = $wigi->{'measures'};
my $steps = $measures->{'steps'};
foreach my $button ( @{$buttons}) {
if ($button->{'room'} && $button->{'button'}) {
my $returner = &subs::edt_button_presser({
timestamp => ($button->{'timestamp'} * 1000),
room => $button->{'room'},
watch_settings => $watch_settings,
button => $button->{'button'},
toggle => $button->{'toggle'},
edt => $edt,
chip_id => $chip_id
});
}
}
my $last_step = 0;
my @measures;
foreach my $step ( @{$steps} ) {
my $ls = $step->{'steps'};
$step->{'steps'} = $step->{'steps'} - $last_step;
$last_step = $ls;
$step->{'timestamp'} = $step->{'timestamp'} * 1000;
if ($step->{'timestamp'} && $step->{'steps'} > 0) {
push @measures, $step;
}
}
if (scalar @measures > 0) {
my $jstep = encode_json \@measures;
&appointment_writer($c, {
app => &subs::unformat_name(&subs::setting_grabber({ app => 'me', setting => 'my_name' })),
type => 'measure',
measures => $jstep,
timestamp => &subs::rightNow(),
seen => 'yes'
});
}
}
}
$c->render(text => 'ok');
};
sub embedded_app_deleter($data) {
my $appt_uuid = $data->{'appt_uuid'};
my $timestamp = &subs::rightNow();
my $chip_id = $data->{'chip_id'} || 'all';
my $chips = &subs::device_lister($timestamp, 'microcontroller', undef, $chip_id);
Mojo::IOLoop->subprocess->run_p(sub {
foreach my $watch ( @{$chips} ) {
if ($watch->{'ip'}) {
my $od = &subs::setting_grabber({ app => 'microcontroller', setting => 'operator_door', subsetting => $watch->{'chip_id'} });
my $op_d = (eval { decode_json $od }) ? decode_json $od : {};
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/delete_job' . '?appt_uuid=' . $appt_uuid . '&authorization=' . $op_d->{'__specs'}->{'authorization'} . '×tamp=' . $timestamp;
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($watch_home)->result;
}
}
});
}
post '/manager/embedded/toggle' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $component = $c->param('component');
my $pin = $c->param('pin');
my $ip = $c->param('ip');
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp');
my $state = $c->param('state');
my $returner = &embedded_toggle({
app => $app,
pin => $pin,
ip => $ip,
edt => $edt,
component => $component,
timestamp => $timestamp,
'state' => $state,
'when' => 'now',
chip_id => $chip_id
});
$c->render(json => $returner);
};
sub embedded_toggle($data) {
my $app = $data->{'app'};
my $pin = $data->{'pin'};
my $ip = $data->{'ip'};
my $edt = $data->{'edt'};
my $state = $data->{'state'};
my $timestamp = $data->{'timestamp'} || &subs::rightNow();
my $component = $data->{'component'};
my $uuid = $data->{'uuid'} || &subs::random_string_creator();
my $appt_uuid = $data->{'appt_uuid'};
my $chip_id = $data->{'chip_id'};
my $measure = $data->{'measure'};
my $when = $data->{'when'} || 'now';
my $ebc = $gb::embedded_components->{$component};
my $syl_count = 10;
$syl_count = 1 unless $edt eq 'microcontroller';
my $syl = &subs::shorthand_name($component, $syl_count);
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $op_d = (eval { decode_json $od }) ? decode_json $od : {};
my $inverted = $op_d->{$syl . $pin}->{'inverted'};
my $save_state = $state;
if ($inverted && $inverted == 1) {
if ($state eq 'on') {
$state = 'off';
$save_state = 'on';
}
elsif ($state == 1) {
$state = 'off';
$save_state = 'on';
}
else {
$state = 'on';
$save_state = 'off';
}
}
elsif (!$state && !$data->{'measure'}) {
$state = &subs::setting_grabber({ app => $app, setting => 'toggle' });
if ($state eq 'on') {
$state = 'off';
$save_state = 'off';
}
elsif ($state eq 'off') {
$state = 'on';
$save_state = 'on';
}
elsif ($state == 1) {
$state = 'off';
$save_state = 'off'
}
else {
$state = 'on';
$save_state = 'on';
}
}
if ($component eq 'servo' && $appt_uuid) {
$state = ($state / 100) * 180;
}
if ($state !~ /[0-9]/) {
&Websocket::send('tab', { console => '$(\'.appointment[app="' . $app . '"]\').find(\'.enabler[type="toggle"\').attr(\'status\',\'' .$save_state . '\').attr(\'src\', \'/images/decipherable/' . $save_state . '.png\');' });
&subs::setting_setter({ app => $app, setting => 'toggle', value => $save_state, source => 'toggle' }) if $data->{'counted'} == 0 || !$data->{'counted'};
}
Mojo::IOLoop->subprocess->run_p(sub {
my $watch = &subs::device_lister($timestamp, $edt, undef, $chip_id);
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/' . $component . '?appt_uuid=' . $appt_uuid . '&uuid=' . $uuid . '&when=' . $when . '&pin=' . $pin . '&state=' . $state . '&component=' . $component . '&authorization=' . $op_d->{'__specs'}->{'authorization'} . '×tamp=' . $timestamp . '&measure=' . $measure;
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($watch_home)->result;
if (eval { $res->result->body }) {
if (eval { decode_json $res->result->body }) {
my $rb = decode_json $res->result->body;
$state = $rb->{'state'};
$pin = $rb->{'pin'};
}
}
my $number_state = $state eq 'on' ? 1 : 0;
});
my $number_state = $state eq 'on' ? 1 : 0;
my $returner = { 'state' => $number_state, formatted_state => $state };
return $returner;
}
post '/manager/embedded/uploader' => sub($c) {
my $timestamp = $c->param('timestamp');
my $port = $c->param('port');
my $edt = $c->param('edt');
my $emerge = $c->param('emerge');
my $chip_id = $c->param('chip_id');
my ($file,$upload_command);
if ($edt eq 'teletype') {
$file = './jt/build/esp32.esp32.esp32s3/jt.ino.bin';
$file = './jt/jt.ino.esp32s3.emerge.bin' if $emerge eq 'yes';
$upload_command = 'python3 ./jt/esptool/4.5.1/esptool.py --chip esp32s3 --port ' .
$port . ' --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 ' .
'./jt/build/esp32.esp32.esp32s3/jt.ino.bootloader.bin 0x8000 ./jt/build/esp32.esp32.esp32s3/jt.ino.partitions.bin 0xe000 ' .
'./jt/esptool/4.5.1/boot_app0.bin 0x10000 ' .
$file;
}
elsif ($edt eq 'watch') {
$file = './jw/build/esp32.esp32.esp32s3/jw.ino.bin';
$file = './jw/jw.ino.esp32s3.emerge.bin' if $emerge eq 'yes';
$upload_command = 'python3 ./jt/esptool/4.5.1/esptool.py --chip esp32s3 --port ' .
$port . ' --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 ' .
'./jw/build/esp32.esp32.esp32s3/jw.ino.bootloader.bin 0x8000 ./jw/build/esp32.esp32.esp32s3/jw.ino.partitions.bin 0xe000 ' .
'./jt/esptool/4.5.1/boot_app0.bin 0x10000 ' .
$file;
}
else {
$c->render('text' => 'no embedded');
}
if ($file && $port) {
my $exec = &subs::run_command('embedded',$upload_command);
&Websocket::send('server', { type => 'append', selector => '#embedded_uploader_result', content => $exec . "
" });
# my $result = `$upload_command`;
$c->render('text' => $exec);
}
};
post '/manager/embedded/ota_uploader' => sub($c) {
my $timestamp = $c->param('timestamp');
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
if ($edt eq 'microcontroller') {
my $watch = &subs::device_lister($timestamp, $edt, undef, $chip_id);
my $file = './jp/alarmclock/build/rp2040.rp2040.rpipico2w/alarmclock.ino.bin';
my $total_size = -s $file;
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/upload/alarmclock.bin?total_size=' . $total_size;
my $ua = Mojo::UserAgent->new();
$ua->transactor->add_generator(stream => sub ($transactor, $tx, $path) {
$tx->req->content->asset(Mojo::Asset::File->new(path => $file));
});
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_wait\').show()', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_fail\').hide()', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_success\').hide()', browser_tab_id => $c->param('browser_tab_id') });
$ua->inactivity_timeout(120000);
my $res = $ua->insecure(1)->post($watch_home => stream => $file )->result;
if ($res->is_success) {
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_wait\').hide()', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_success\').show()', browser_tab_id => $c->param('browser_tab_id') });
}
else {
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_wait\').hide()', browser_tab_id => $c->param('browser_tab_id') });
&Websocket::send('tab', { console => '$(\'#embedded_ota_uploader_fail\').show()', browser_tab_id => $c->param('browser_tab_id') });
}
# my $tx = $t->tx(POST => 'http://example.com' => form => {mytext => {file =
#> '/foo.txt'}});
$c->render(text => 'yes');
}
else {
$c->render(text => 'no');
}
};
get '/manager/embedded/teletype_backup' => sub($c) {
my $ip = $c->param('ip');
my $mac = $c->param('mac');
my $timestamp = $c->param('timestamp');
my $teletype = &subs::device_lister($timestamp,'teletype');
my $chip_id = $c->param('chip_id');
$c->param('reason' => 'teletype_backup');
Mojo::IOLoop->subprocess->run_p(sub {
if ($teletype->{'ip'} && !$teletype->{'uuid'} && $teletype->{'ip'} eq $ip) {
my $ping = 'timeout .2 ping -c 1 ' . $teletype->{'ip'};
my $ping_test = `$ping`;
my $backup = &subs::backup_now($c);
$backup = encode_json $backup;
if ($ping_test =~ /ttl/gi) {
my $teletype_url = 'http://' . $teletype->{'ip'} . ':' . $config->{'port'} . '/backup?backup=' . $backup . '×tamp=' . $timestamp;
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($teletype_url)->result;
}
}
});
};
get '/manager/embedded/jobs' => sub($c) {
my $ip = $c->param('ip');
my $mac = $c->param('mac');
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp');
my $mc = &subs::device_lister($timestamp, $edt, undef, $chip_id);
my $wat_set = &subs::setting_grabber({ app => $edt, setting => 'operator_door', device => $device, subsetting => $chip_id });;
my $watch_settings = eval { return decode_json $wat_set } || {};
my $auth = $watch_settings->{'__specs'}->{'authorization'};
my $author = `echo $auth | base64 --decode`;
my $authorization = &subs::note_decrypter($watch_settings->{'__shutup'}->{'patience'}, $author);
my $url = 'http://' . $mc->{'ip'} . ':' . $config->{'port'} . '/jobs?authorization=' . $authorization;
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($url)->result;
my $returner = {};
if ($res->is_success) {
my $jobs = eval { return decode_json $res->body } || {};
$returner->{'jobs'} = $jobs;
$returner->{'html'} = $c->render_to_string(
template => 'embedded/jobs',
jobs => $jobs,
op_d => $watch_settings
);
}
$c->render(json => $returner);
};
post '/manager/embedded/delete_job' => sub($c) {
my $appt_uuid = $c->param('appt_uuid');
my $chip_id = $c->param('chip_id');
my $uuid = $c->param('uuid');
&embedded_app_deleter({ appt_uuid => $appt_uuid, $chip_id });
$c->render(json => { uuid => $uuid, appt_uuid => $appt_uuid });
};
post '/manager/watch/assign' => sub($c) {
my $edt = $c->param('edt');
my $ip = $c->param('ip');
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $pre_value = $c->param('pre_value');
my $numero = $c->param('numero');
my $component = $c->param('component');
my $chip_id = $c->param('chip_id');
my $syl_count = 10;
$syl_count = 1 unless $edt eq 'microcontroller';
my $syl = &subs::shorthand_name($component, $syl_count);
my $type = 'text';
($app,$type) = &subs::typesetter($app);
&subs::setting_setter({ app => $app, setting => 'pos', value => $type });
my $init = &subs::setting_initializer($app,$timestamp);
$app = $init->{'app'};
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $op_d = (eval { decode_json $od }) ? decode_json $od : {};
my $colour = &subs::setting_grabber({ app => $app, setting=> 'colour' });
$colour =~ s/^#//gi;
my @rgb = map $_ , unpack 'C*', pack 'H*', $colour;
$op_d->{$syl . $numero} = {
'colour' => $colour,
rgb => \@rgb,
shorthand_name => &subs::shorthand_name(&subs::format_name($app)),
app => $app,
movement => $op_d->{$syl . $numero}->{'movement'} || 'command',
inverted => $op_d->{$syl . $numero}->{'inverted'},
numero => $numero,
measure => $op_d->{$syl . $numero}->{'measure'},
toggle => $op_d->{$syl . $numero }->{'toggle'} || 0,
direction => $gb::embedded_components->{$component}->{'direction'},
component => $component,
uuid => &subs::random_string_creator(),
name => $op_d->{$syl . $numero}->{'name'}
};
if ($app eq '') {
delete $op_d->{$syl . $numero};
}
my $json_od = encode_json $op_d;
&subs::setting_setter({ app => $edt, setting => 'operator_door', value => $json_od, subsetting => $chip_id });
my $pia = eval { return decode_json &subs::setting_grabber({ app => $pre_value, setting => 'ia' }) } || {};
delete $pia->{$chip_id}->{$numero};
my $jpia = encode_json $pia;
&subs::setting_setter({ app => $pre_value, setting => 'ia', value => $jpia });
my $ia = eval { return decode_json &subs::setting_grabber({ app => $app, setting => 'ia'}) } || {};
$ia->{$chip_id}->{$numero} = {
movement => $op_d->{$syl . $numero}->{'movement'},
ip => $ip,
edt => $edt,
pin => $numero,
direction => $gb::embedded_components->{$component}->{'direction'},
component => $component
};
my $jia = encode_json $ia;
&subs::setting_setter({ app => $app, setting => 'ia', value => $jia });
my $returner = &embedded_pin_grabber({
edt => $edt,
numero => $numero,
component => $component,
chip_id => $chip_id,
timestamp => $timestamp,
component => $component
});
my $res = &now_me({ timestamp => $timestamp, edt => $edt, chip_id => $chip_id, browser_tab_id => $c->param('browser_tab_id') });
$c->render('json' => { app => $app, formatted_name => &subs::format_name($app ), html => $returner->{'html'} });
};
post '/manager/watch/setting' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $numero = $c->param('numero');
my $movement = $c->param('movement');
my $setting = $c->param('setting');
my $component = $c->param('component');
my $syl_count = 10;
my $chip_id = $c->param('chip_id');
my $percentage = $c->param('percentage');
$syl_count = 1 unless $edt eq 'microcontroller';
my $syl = &subs::shorthand_name($component, $syl_count);
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $op_d = (eval { decode_json $od }) ? decode_json $od : {};
my $app = $op_d->{$syl . $numero}->{app};
$op_d->{$syl . $numero}->{$setting} = $movement;
if ($percentage) {
$op_d->{$syl . $numero}->{$setting . '_percentage'} = $percentage;
}
my $json_od = encode_json $op_d;
&subs::setting_setter({ app => $edt, setting => 'operator_door', value => $json_od, timestamp => $timestamp, subsetting => $chip_id });
my $jia = &subs::setting_grabber({ app => $app, setting => 'ia' });
if ($jia) {
my $ia = eval { return decode_json $jia } || {};
$ia->{$chip_id}->{$numero}->{$setting} = $movement;
if ($percentage) {
$ia->{$chip_id}->{$numero}->{$setting . '_percentage'} = $percentage;
}
my $jia = encode_json $ia;
&subs::setting_setter({ app => $app, setting => 'ia', value => $jia });
}
my $returner = &embedded_pin_grabber({
edt => $edt,
numero => $numero,
component => $component,
chip_id => $chip_id,
timestamp => $timestamp
});
my $res = &now_me({ timestamp => $timestamp, edt => $edt, chip_id => $chip_id, browser_tab_id => $c->param('browser_tab_id') });
$c->render(json => $returner );
};
get '/manager/watch/diagram' => sub($c) {
my $uuid = $c->param('uuid');
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'embedded', setting => 'diagrams' }) } || [];
@{$diagrams} = grep { $_->{'uuid'} eq $uuid } @{$diagrams};
my $diagram = $diagrams->[0];
my $op_d = eval { return decode_json &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id }) } || {};
my $returner = { uuid => $uuid, diagram => $diagram };
$returner->{'html'} = $c->render_to_string(
template => 'embedded/diagram',
d => $diagram,
op_d => $op_d
);
$c->render(json => $returner);
};
post '/manager/watch/diagram' => sub($c) {
my $edt = $c->param('edt');
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp');
my $diagram = eval { return decode_json $c->param('diagram') } || {};
my $op_d = eval { return decode_json &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id }) } || {};
my $diagrams = eval { return decode_json &subs::setting_grabber({ app => 'embedded', setting => 'diagrams'}) } || [];
my $returner = { diagram => $diagram };
foreach my $d ( @{$diagrams} ) {
if ($d->{'uuid'} eq $diagram->{'file'}->{'uuid'}) {
$d->{'components'} = $diagram->{'components'};
}
}
my $jdiagrams = encode_json $diagrams;
&subs::setting_setter({ app => 'embedded', setting => 'diagrams', value => $jdiagrams });
$returner->{'diagrams'} = $diagrams;
$c->render(json => $returner);
};
post '/manager/watch/measure' => sub($c) {
my $edt = $c->param('edt');
my $component = $c->param('component');
my $numero = $c->param('numero');
my $syl_count = 10;
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp') || &subs::rightNow();
$syl_count = 1 unless $edt eq 'microcontroller';
my $syl = &subs::shorthand_name($component, $syl_count);
my $measure = $c->param('measure');
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $op_d = eval { return decode_json $od } || {};
$op_d->{$syl . $numero}->{'measure'} = $measure;
my $app = $op_d->{$syl . $numero}->{'app'};
my $jopd = encode_json $op_d;
&subs::setting_setter({ app => $edt, setting => 'operator_door', subsetting => $chip_id, value => $jopd });
my $jia = &subs::setting_grabber({ app => $app, setting => 'ia' });
if ($jia) {
my $ia = eval { return decode_json $jia } || {};
$ia->{$chip_id}->{$numero}->{'measure'} = $measure;
$jia = encode_json $ia;
&subs::setting_setter({ app => $app, setting => 'ia', value => $jia });
}
my $returner = &embedded_pin_grabber({
edt => $edt,
numero => $numero,
component => $component,
chip_id => $chip_id,
timestamp => $timestamp
});
$c->render(json => $returner);
};
sub send_telephone($app,$msg) {
my $timestamp = &subs::rightNow();
foreach my $w ( qw/teletype watch microcontroller/ ) {
my $chips = &subs::device_lister($timestamp,$w,undef, 'all');
foreach my $watch ( @{$chips} ) {
my $od = &subs::setting_grabber({ 'app' => $watch->{'purpose'}, 'setting' => 'operator_door', subsetting => $watch->{'chip_id'} });
my $op_d = (eval { decode_json $od }) ? decode_json $od : {};
if ($watch->{'ip'} && !$watch->{'uuid'}) {
my $ping = 'timeout .2 ping -c 1 ' . $watch->{'ip'};
my $ping_test = `$ping`;
if ($ping_test =~ /ttl/gi) {
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/send_telephone?app=' . $app . '&msg=' .
&subs::unformat_name($msg) . '×tamp=' . $timestamp;
Mojo::IOLoop->subprocess->run_p(sub {
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($watch_home)->result;
});
}
sleep 2;
}
}
}
}
sub now_me($data) {
my $timestamp = $data->{'timestamp'};
my $edt = $data->{'edt'};
my $ip = $data->{'ip'};
my $chip_id = $data->{'chip_id'};
my $name = $data->{'name'};
my $server_time = time();
my @t = localtime(time);
my $is_dst = $t[8];
my $offset = timegm(@t) - timelocal(@t);
if ($is_dst == 0 && $edt eq 'watch') {
$server_time = $server_time + (1000 * 3600);
}
my $watch = &subs::device_lister($timestamp, $edt, undef, $chip_id);
my $watch_port = $ENV{PORT_BELL};
my $ws_port = $ENV{PORT_MSG};
my $od = &subs::setting_grabber({ app => $edt, setting => 'operator_door', device => $device, subsetting => $chip_id });
my $op_d = eval { decode_json $od } || {};
$name = $op_d->{'__specs'}->{'name'} unless $data->{'name'};
$ip = $watch->{'homebase'} unless $ip;
$op_d->{'__specs'}->{'room_count'} = &subs::setting_grabber({'app' => 'me', setting => 'room_count'}) || $op_d->{'__specs'}->{'room_count'} || 2;
$op_d->{'__specs'}->{'homebase'} = $watch->{'homebase'} . ':' . $watch_port;
$op_d->{'__specs'}->{'ip'} = $watch->{'homebase'};
$op_d->{'__specs'}->{'edt'} = $edt;
$op_d->{'__specs'}->{'name'} = $name;
$op_d->{'__specs'}->{'time'} = {
sec => $t[0],
min => $t[1],
hour => $t[2],
day => $t[3],
month => $t[4] + 1,
year => $t[5] + 1900
};
my $computer_name = &subs::setting_grabber({ app => 'me', setting => 'computer_name' });
$op_d->{'__specs'}->{'computer'} = &manager_file_maker('') || $op_d->{'__specs'}->{'homebase'};
my $room_count = $op_d->{'__specs'}->{'room_count'};
if ($edt eq 'watch') {
$op_d->{'__specs'}->{'room_max'} = 6;
}
elsif ($edt eq 'teletype') {
$op_d->{'__specs'}->{'room_max'} = 8;
}
else {
$op_d->{'__specs'}->{'room_max'} = 1;
}
my $room_max = $op_d->{'__specs'}->{'room_max'};
my $patience = &subs::random_string_creator(36);
my $au = &subs::random_string_creator(27);
my $auth = &subs::note_encrypter($patience, $au );
my $authorization = `(echo $auth) | base64 -w 0`;
$op_d->{'__shutup'}->{'patience'} = $patience;
$op_d->{'__specs'}->{'authorization'} = $authorization;
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/now_me?name=' . $name . '&ip='. $watch->{'homebase'} . '&homebase=' . $watch->{'homebase'} . ':' . $watch_port
. '×tamp=' . $server_time . '&offset=' . $offset . '&authorization=' . $authorization . '&room_count=' . $room_count . '&browser_tab_id=' . $data->{'browser_tab_id'}
. '&room_max=' . $room_max . '&twshomebase=' . $watch->{'homebase'} . ':' . $ENV{PORT_COMS} . '&thomebase=' . $watch->{'homebase'} . ':' . $ENV{PORT_BESTOW};
my $ua = Mojo::UserAgent->new();
foreach my $gah ( qw/project person community club team/ ) {
my $pros = &subs::db_query('select * from settings where setting=? and value=?', 'pos',$gah);
my $professionals = $pros->hashes;
$op_d->{'__specs'}->{'chat'}->{$gah} = "";
foreach my $sc ( keys %{$gb::social_constructs} ) {
if ($gb::social_constructs->{$sc}->{'sing'} eq $gah) {
$op_d->{'__specs'}->{'chat'}->{$gah} .= $gb::social_constructs->{$sc}->{'def'} . "\n";
}
}
foreach my $pro ( @{$professionals} ) {
$op_d->{'__specs'}->{'chat'}->{$gah} .= &subs::format_name($pro->{'app'}) . "\n";
}
}
my $contacters = &subs::db_query('select * from tickets where status = ?', 'active' );
my $contacts = $contacters->hashes;
$op_d->{'__specs'}->{'chat'}->{'contacts'} = "";
foreach my $conmen ( @{$contacts} ) {
$op_d->{'__specs'}->{'chat'}->{'contacts'} .= $conmen->{'name'} . "\n";
}
my $ip = $watch->{'ip'};
my $json_op = encode_json $op_d;
&subs::setting_setter({ app => $edt, setting => 'operator_door', value => $json_op, subsetting => $chip_id });
my $res = $ua->insecure(1)->get($watch_home)->result;
if ($edt eq 'microcontroller') {
if (eval { $res->result->body }) {
if (eval { decode_json $res->result->body }) {
my $rb = decode_json $res->result->body;
foreach my $info ( keys %{$rb} ) {
$op_d->{'__specs'}->{$info} = $res->{$info};
}
}
}
$json_op = encode_json $op_d;
&subs::setting_setter({ app => $edt, setting => 'operator_door', value => $json_op, subsetting => $chip_id });
}
return $res;
}
get '/manager/watch/set_proxy' => sub ($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $lat_calc = 110.574;
my $long_calc = (111.320 * cos($lat_calc));
my $scope = $c->param('scope') || 20;
my $chip_id = $c->param('chip_id');
my $q = &subs::db_query('select * from continent where uuid = ? and timestamp=?',$uuid, $timestamp);
my $locations = $q->hashes;
&subs::setting_setter({ app => $edt, setting => 'watch_scope', value => $scope, subsetting => $chip_id });
my $proxies = { near => $locations, far => [], here => {}, scope => $scope };
foreach my $l ( @{$locations} ) {
my $operator_door = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $od = decode_json $operator_door;
my $operator = $od->{'b1'}->{'app'};
&subs::db_update('continent', {
operator => $operator,
operator_door => $operator_door,
type => 'proxy_set',
scope => $scope
},{ uuid => $l->{'uuid'}, timestamp => $timestamp });
my $sloop = &subs::db_query('select * from continent where timestamp=? and uuid=?',$timestamp, $l->{'uuid'});
my $slur = $sloop->hashes;
my $sl = $slur->[0];
$proxies->{'here'} = $sl;
}
$c->render(json => $proxies);
};
get '/manager/watch/list_proxy' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $chip_id = $c->param('chip_id');
my $q = &subs::db_query('select * from continent where uuid = ? and timestamp=?',$uuid,$timestamp);
my $locations = $q->hashes;
my $scope = $c->param('scope') ? $c->param('scope') : 20;
&subs::setting_setter({ app => $edt, setting => 'watch_scope', value => $scope, subsetting => $chip_id });
my $proxies = { near => [], far => [], here => {}, scope => $scope };
my $operator_door = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $od = decode_json $operator_door;
foreach my $l (@{$locations}) {
my $operator = $od->{'b1'}->{'app'};
&subs::db_update('continent',{
operator => $operator,
operator_door => $operator_door,
type => 'proxy_load'
}, {
uuid => $l->{'uuid'}, timestamp => $l->{'timestamp'}
});
my $similar = &subs::db_query('select * from continent where type=?', 'proxy_set');
foreach my $sl (@{$similar->hashes}) {
my $lat = ($sl->{'longitude'} - $l->{'longitude'});
my $long = ($sl->{'longitude'} - $l->{'longitude'});
my $radius = 6372.8;
my @BNA = (deg2rad($l->{'longitude'}), deg2rad(90 - $l->{'latitude'}));
my @LAX = (deg2rad($sl->{'longitude'}), deg2rad(90 - $sl->{'latitude'}));
my $distance = great_circle_distance(@BNA, @LAX, $radius);
my $metres = $distance * 1000;
$sl->{'distance'} = sprintf("%2f", $metres);
$sl->{'ago'} = &subs::duration_sayer(($timestamp - $sl->{'timestamp'}) / 1000);
if ($metres <= $scope) {
push @{$proxies->{'near'}}, $sl;
}
}
push @{$proxies->{'near'}}, $l;
$proxies->{'here'} = $l;
}
$proxies->{'html'} = $c->render_to_string(
template => 'embedded/proxy',
proxies => $proxies,
);
$c->render(json => $proxies);
};
post '/manager/watch/proxy_load' => sub($c) {
my $edt = $c->param('edt');
my $uuid = $c->param('uuid');
my $chip_id = $c->param('chip_id');
my $timestamp = $c->param('timestamp');
my $locations = &subs::db_query('select * from continent where uuid=?', $uuid)->hashes;
my $location = $locations->[0];
my $operator_door = decode_json $location->{'operator_door'};
&subs::setting_setter({ app => $edt, setting => 'operator_door', value => $location->{'operator_door'}, subsetting => $chip_id });
$c->render('text' => &embedded_grabber($c,$timestamp));
};
post '/manager/watch/proxy_here' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $chip_id = $c->param('chip_id');
my $locations = &subs::db_query('select * from continent where timestamp=?', $timestamp)->hashes;
my $location = $locations->[0];
&subs::db_update('continent', {
latitude => $location->{'latitude'},
longitude => $location->{'longitude'},
}, {
uuid => $uuid
});
$locations = &subs::db_query('select * from continent where uuid=?', $uuid)->hashes;
$location = $locations->[0];
$c->render(json => $location);
};
post '/manager/watch/proxy_save' => sub($c) {
my $edt = $c->param('edt');
my $timestamp = $c->param('timestamp');
my $uuid = $c->param('uuid');
my $chip_id = $c->param('chip_id');
my $room_max = &subs::setting_grabber({ app => 'me', setting => 'room_max' });
my $room_count = &subs::setting_grabber({ app => 'me', setting => 'room_count' });
my $op = &subs::setting_grabber({ app => $edt, setting => 'operator_door', subsetting => $chip_id });
my $watch_settings = eval { return decode_json $op } || {};
for (my $n = 1; $n <= $room_max * $room_count; $n++) {
my $app = $watch_settings->{"b" . $n}->{'app'};
my $colour = $watch_settings->{"b" . $n}->{'colour'};
my $movement = $watch_settings->{"b" . $n}->{'movement'};
$colour =~ s/^#//gi;
my @rgb = map $_ , unpack 'C*', pack 'H*', $colour;
$watch_settings->{"b" . $n} = {
'colour' => $colour,
rgb => \@rgb,
shorthand_name => &subs::shorthand_name(&subs::format_name($app)),
app => $app,
movement => $movement,
numero => $n
};
}
my $json_watch = encode_json $watch_settings;
my $q = &subs::db_update('continent', {
timestamp => $timestamp,
operator_door => $json_watch,
operator => $watch_settings->{'b1'}->{'app'}
}, {
uuid => $uuid
});
$c->render(text => $uuid);
};
post '/manager/watch/delete_proxy' => sub($c) {
if ($c->param('uuid')) {
&subs::db_delete('continent', { uuid => $c->param('uuid') });
}
$c->render(text => $c->param('uuid') );
};
get '/manager/past_life_recall' => sub($c) {
my $timestamp = $c->param('timestamp');
my $direction = $c->param('direction');
my $room_check = $c->param('room_check');
my $report = {};
my $query = 'select * from websockets where app= ? and timestamp < ? ORDER BY timestamp DESC LIMIT 1';
my $results;
if ($direction eq 'load') {
$query = 'select * from websockets where app= ? and timestamp = ?';
$results = &subs::db_query($query, 'tab', $timestamp);
}
elsif ($direction eq 'forget') {
$query = 'delete from websockets where app= ? and timestamp = ?';
$results = &subs::db_query($query, 'tab', $timestamp);
}
elsif ($direction eq 'ff') {
$query = 'select * from websockets where app= ? and timestamp > ? order by timestamp ASC LIMIT 1';
if ($room_check eq 'true') {
$query = 'select * from websockets where app= ? and timestamp > ? and room is not null order by timestamp ASC LIMIT 1';
}
$results = &subs::db_query($query, 'tab', $timestamp);
}
elsif ($direction eq 'rew') {
if ($room_check eq 'true') {
$query = 'select * from websockets where app= ? and timestamp < ? and room is not null order by timestamp DESC LIMIT 1';
}
$results = &subs::db_query($query, 'tab', $timestamp);
}
my $rooms = $results->hashes;
foreach my $room ( @{$rooms} ) {
my $drawings = &subs::db_query('select * from appointments where browser_tab_id=? and file is not null',$room->{'browser_tab_id'})->hashes;
my $portfolio = [];
foreach my $d ( @{$drawings} ) {
my $files = eval { return decode_json $d->{'file'} } || [];
foreach my $f ( grep { $_->{'type'} eq 'image' || $_->{'type'} eq 'video' } @{$files} ) {
push @{$portfolio}, $f;
}
}
my $lifetime = localtime( $room->{'timestamp'} / 1000 )->strftime('%a %B %d %Y %I:%M:%S%P');
my $windows = eval { return decode_json $room->{'windows'} } || {};
my $appt_count = scalar %{$windows};
my $playbook = ($room->{'room'} || $room->{'browser_tab_id'} ) . "
$lifetime
";
# next unless scalar keys %{$windows} > 0;
foreach my $w ( keys %{$windows} ) {
$playbook .= '' . &subs::format_name($windows->{$w}->{'app'}) . '
';
}
$report = {
room => $room->{'room'},
timestamp => $room->{'timestamp'},
user_agent => $room->{'user_agent'},
lifetime => $lifetime,
json_windows => $room->{'windows'},
windows => $windows,
appt_count => $appt_count,
playbook => $playbook,
browser_tab_id => $room->{'browser_tab_id'},
portfolio => $portfolio
};
}
$c->render(json => $report);
};
get '/manager/marker' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app') || 'marker';
my $browser_tab_id = $c->param('browser_tab_id');
my ($db,$database,$sql) = &subs::database_grabber();
my $q = &subs::db_query('select * from appointments where app = ? and type= ?', $app, 'image' );
my $drawings = $q->hashes;
my $contents = $c->render_to_string(
template => 'marker',
window_maker => 'yes',
drawings => $drawings
);
my $website = &Manager::window_maker({ user_agent => $c->param('user_agent'), app => 'marker', contents => $contents }, $timestamp);
$c->render(text => $website);
};
post '/manager/snapshot_save' => sub($c) {
my $timestamp = $c->param('timestamp');
my $app = &subs::unformat_name($c->param('app'));
my $snapshot = $c->param('snapshot');
my @snapshot = split ',', $snapshot;
shift @snapshot;
$snapshot = join ',', @snapshot;
$snapshot = decode_base64($snapshot);
my $folder = &subs::setting_grabber( { app => 'misc', setting => 'photo_location', device => $device } );
my $location = &subs::home($folder) . '/' . $app;
my $filename = $location . '/' . $timestamp . '.png';
write_file($filename,$snapshot);
my $jfile = encode_json [{ server_time => &subs::rightNow(), f => $filename, uuid => &subs::random_string_creator(8), type => 'image' }];
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
type => 'image',
file => $jfile,
uuid => &subs::random_string_creator(20),
duration => '1'
};
&appointment_writer($c,$write);
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
$c->render(json => $write);
};
post '/manager/marker/save' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $marker = $c->param('marker');
my $image = $c->param('img');
my $paper = $c->param('paper');
my $app = &subs::unformat_name($c->param('app'));
my $browser_tab_id = $c->param('browser_tab_id');
my ($db,$database,$sql) = &subs::database_grabber();
my @image = split ',', $image;
shift @image;
$image = join ',', @image;
$image = decode_base64($image);
my $folder = &subs::setting_grabber( { app => 'misc', setting => 'photo_location', device => $device } );
my $location = &subs::home($folder) . '/' . $app;
my $filename = $location . '/' . $timestamp . '.png';
write_file($filename,$image);
my $jfile = encode_json [{ server_time => &subs::rightNow(), f => $filename, uuid => &subs::random_string_creator(8), type => 'image' }];
my $write = {
timestamp => $timestamp,
app => &subs::unformat_name($app),
type => 'image',
file => $jfile,
uuid => &subs::random_string_creator(20),
duration => '1',
browser_tab_id => $browser_tab_id
};
&appointment_writer($c,$write);
&subs::file_encrypter({ app => $app, timestamp => $timestamp, suds => $c->session('suds') });
my $q = &subs::db_query('select * from appointments where app = ? and type=?',$app,'image');
my $drawings = $q->hashes;
my $json = encode_json $drawings || [];
$c->render(json => $json);
};
post '/manager/marker/delete' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $file_uuid = $c->param('file_uuid');
my $app_uuid = $c->param('app_uuid');
my $app = $c->param('app');
my $server_time = $c->param('server_time');
&delete_file({ app => $app, app_uuid => $app_uuid, file_uuid => $file_uuid });
$c->render(text => 'ok');
};
get '/manager/marker/gallery' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $app = $c->param('app');
my $drawings;
if ($app) {
$drawings = &subs::db_select('drawings', undef, { app => $app })->hashes;
}
else {
$drawings = &subs::db_select('drawings')->hashes;
}
my $returner = { app => $app, timestamp => $timestamp, drawings => $drawings };
$returner->{'html'} = '' . &subs::format_name($app || 'All') . '
';
foreach my $drawing ( @{$drawings} ) {
$returner->{'html'} .= '

';
$returner->{'html'} .= '
';
}
$returner->{'html'} .= '
';
$c->render(json => $returner);
};
post '/manager/room_namer' => sub ($c) {
my $timestamp = $c->param('timestamp');
my $room_name = $c->param('room_name');
my $app = $c->param('app');
my $browser_tab_id = $c->param('browser_tab_id');
my ($db,$database,$sql) = &subs::database_grabber();
my $ug = Data::UUID->new;
my $uuid = $ug->create_str();
my $up = &subs::db_update('websockets', { room => $room_name }, { app => 'tab', browser_tab_id => $browser_tab_id });
my $room = { browser_tab_id => $uuid, formatted_name => &subs::format_name($room_name), room_name => $room_name, timestamp => $timestamp };
$c->render(json => $room);
};
post '/manager/new_room' => sub ($c) {
my $ug = Data::UUID->new;
my $uuid = $ug->create_str();
my $room = {
timestamp => $c->param('timestamp'),
room_name => $c->param('room_name'),
app => $c->param('app'),
browser_tab_id => $uuid
};
$c->render(json => $room);
};
get '/manager/update_database' => sub ($c) {
$c->render('text' => 'no updates');
&update_database($c);
};
sub update_database($c) {
&subs::cache_delete({ app => 'me', context => 'pseudonyms' });
my $commands = [
'CREATE INDEX idx1_settings on settings (setting)',
'CREATE INDEX idx2_settings on settings (setting,device)',
'CREATE INDEX idx3_settings on settings (setting,value)',
'CREATE INDEX idx4_settings on settings (setting,device,value)',
'CREATE INDEX idx1_appts on appointments (app)',
'CREATE INDEX idx2_appts on appointments (app,timestamp)',
'CREATE INDEX idx3_appts on appointments (app,uuid)',
'CREATE INDEX idx4_appts on appointments (uuid)',
'CREATE INDEX idx5_appts on appointments (app,timestamp)',
'CREATE INDEX idx6_appts on appointments (app,server_time)',
'CREATE INDEX idx7_appts on appointments (timestamp,seen)',
'CREATE INDEX idx8_appts on appointments (timestamp, stop_timestamp, seen, stop_seen)',
'CREATE INDEX idx9_appts on appointments (stop_timestamp,stop_seen)',
'CREATE INDEX idx1_ws on websockets (app,browser_tab_id)',
'CREATE INDEX idx2_ws on websockets (browser_tab_id)',
'CREATE INDEX idx1_continent on continent (app)',
'CREATE INDEX idx2_continent on continent (app,uuid)',
'CREATE INDEX idx1_security on security (level)',
'CREATE INDEX idx2_security on security (level,server_time)',
'CREATE INDEX idx1_cache on cache (app,device,context,subcontext)',
'CREATE INDEX idx1_backups on backups (signatorial,recipient)',
'CREATE INDEX idx1_mailbox on mailbox (contact)',
'CREATE INDEX idx2_mailbox on mailbox (community,club,team,project,account,person)',
'alter table drawings add column app varchar(255)',
'alter table option add column description VARCHAR(2000)',
'alter table model add column description VARCHAR(2000)',
'alter table option_category add column description VARCHAR(2000)',
'alter table option add column discount VARCHAR(25)',
'alter table model add column discount VARCHAR(25)',
'alter table option_category add column discount VARCHAR(25)',
'alter table option add column markup VARCHAR(25)',
'alter table model add column markup VARCHAR(25)',
'alter table option_category add column markup VARCHAR(25)',
'alter table subcategory add column description VARCHAR(2000)',
'alter table subcategory add column discount VARCHAR(25)',
'alter table subcategory add column markup VARCHAR(25)',
'alter table model add column manufacturer VARCHAR(255)',
'alter table option add column manufacturer VARCHAR(255)',
'alter table option_category add column manufacturer VARCHAR(255)',
'alter table subcategory add column manufacturer VARCHAR(255)',
'alter table option drop column model',
'alter table option drop column option_category',
'alter table appointments add column balance VARCHAR(25)',
'alter table appointments add column measures LONGTEXT',
'alter table appointments add column manufacturer LONGTEXT',
'alter table tickets add column access_log LONGTEXT',
'alter table neighbour_link add column credential LONGTEXT',
'alter table neighbour_link add column name VARCHAR(255)',
'alter table appointments add column encryption_standard VARCHAR(25)',
'alter table appointments add column options LONGTEXT',
'drop table tracks',
'alter table appointments add column source_uuid VARCHAR(255)',
'alter table appointments add column currency VARCHAR(10)',
'drop table characteristics',
'drop table drawings',
'alter table websockets add column ticket_uuid VARCHAR(255)',
'alter table notifications add column role VARCHAR(100)',
'alter table notifications drop column type',
'alter table notifications add column app VARCHAR(255)',
'alter table mailbox add column phone VARCHAR(25)',
'alter table mailbox add column email VARCHAR(255)',
'alter table mailbox add column subject VARCHAR(1000)',
'alter table mailbox add column attachments LONGTEXT',
'alter table backups add column enc_file VARCHAR(255)',
'alter table remote_machines add column hostname VARCHAR(255)',
'alter table devices add column chip_ids LONGTEXT',
'alter table appointments add column stop_seen VARCHAR(5)',
'alter table appointments add column stop_timestamp VARCHAR(255)',
'alter table settings add column subsetting VARCHAR(255)',
'alter table websocket_messages add column patience VARCHAR(5)',
'alter table websockets drop column patience',
'alter table appointments add column duties LONGTEXT',
'alter table appointments add column next_duty VARCHAR(255)',
];
foreach my $t ( qw/model option option_category subcategory/) {
push @{$commands}, 'alter table ' . $t . ' add column def VARCHAR(10)';
push @{$commands}, 'alter table ' . $t . ' add column quantity VARCHAR(10)';
push @{$commands}, 'alter table ' . $t . ' add column unit VARCHAR(10)';
push @{$commands}, 'alter table ' . $t . ' add column save_app VARCHAR(10)';
push @{$commands}, 'alter table ' . $t . ' add column file LONGTEXT';
push @{$commands}, 'alter table ' . $t . ' add column delay_start VARCHAR(255)';
push @{$commands}, 'alter table ' . $t . ' add column delay_stop VARCHAR(255)';
}
my ($db,$database,$sql) = &subs::database_grabber();
foreach my $command (@{$commands}) {
eval { &subs::db_query($command) };
}
}
post '/manager/setting_setter' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $setting = $c->param('setting');
my $value = $c->param('value');
my $subsetting = $c->param('subsetting');
my $timestamp = $c->param('timestamp');
my $s = &subs::setting_setter({ app => $app, setting => $setting, value => $value, timestamp => $timestamp, subsetting => $subsetting });
$c->render(json => $s);
};
get '/manager/setting_grabber' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $s = &subs::setting_grabber({ app => $app, setting => $c->param('setting'), subsetting => $c->param('subsetting') });
$c->render(json => $s);
};
post '/manager/setting_deleter' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $s = &subs::setting_deleter({ app => $app, setting => $c->param('setting'), device => $c->param('device') });
$c->render(json => $s);
};
get '/manager/settings_grabber' => sub($c) {
my $app = &subs::unformat_name($c->param('app'));
my $device = &subs::unformat_name($c->param('device'));
my $s = &subs::settings::grabber({ app => $app, device => $device });
$c->render(json => $s);
};
get '/manager/ago' => sub ($c) {
my $ago = $c->param('ago');
my $timestamp = $c->param('timestamp') || &subs::rightNow();
$timestamp = &subs::ago_calc($ago,$timestamp);
$c->render(text => $timestamp);
};
websocket '/observer/ws' => sub ($c) {
my $browser_tab_id = $c->param('browser_tab_id');
$gb::paperboy->{$browser_tab_id} = $c->tx;
$c->on(message => sub ($ows, $msg) {
my $m = decode_json $msg;
if ($m->{'type'} eq 'heartbeat') {
$ows->send($msg);
}
elsif ($m->{'type'} eq 'refresher') {
my ($db,$database,$sql) = &subs::database_grabber();
my $server_time = &subs::rightNow();
my $q = &subs::db_query('select * from magazine where timestamp >= ? and timestamp <= ? and status=?', $m->{'last_paper_delivered'},$server_time,'publish');
my $papers = $q->hashes;
foreach my $p ( @{$papers} ) {
my $papes = encode_json $p;
$ows->send($papes);
}
}
});
$c->on(close => sub ($ows, $msg) {
$gb::paperboy->{$browser_tab_id} = undef;
});
};
websocket '/mail/ws' => sub ($c) {
my $me = &manager_file_maker($c->session('name'));
my $browser_tab_id = $c->param('browser_tab_id');
my $picker = eval { return decode_json $c->param('picker') } || {};
if ($c->param('phone') && $c->param('phone') ne 'null' && $c->param('phone') ne 'undefined') {
$gb::mailws->{$c->param('phone')}->{$browser_tab_id} = $c->tx;
}
elsif ($c->param('email') && $c->param('email') ne 'null' && $c->param('email') ne 'undefined') {
$gb::mailws->{$c->param('email')}->{$browser_tab_id} = $c->tx;
}
elsif ($c->param('mail_contact') && $c->param('mail_contact') ne 'null') {
$gb::mailws->{$c->param('mail_contact')}->{$browser_tab_id} = $c->tx;
}
elsif ($c->session('privilege') eq 'guest') {
$gb::mailws->{$c->session('ticket_uuid')}->{$browser_tab_id} = $c->tx;
}
else {
$gb::mailws->{$picker->{'people'}}->{$picker->{'accounts'}}->{$picker->{'projects'}}->{$picker->{'teams'}}->{$picker->{'clubs'}}->{$picker->{'communities'}}->{$browser_tab_id} = $c->tx;
}
my $name = $c->session('name');
$c->on(message => sub ($mws, $msg) {
my $m = decode_json $msg;
$m->{'uuid'} = &subs::random_string_creator(35);
if ($m->{'type'} eq 'heartbeat') {
if ($c->session('privilege') eq 'citizen') {
my ($db,$database,$sql) = &subs::database_grabber();
my $publics = &subs::db_query('select * from mailbox where status=?', 'public');
my $public = $publics->hashes;
foreach my $p ( @{$public} ) {
&subs::db_query('update mailbox set status=?, body =? where uuid =?', 'sent', &subs::note_encrypter($c->session('suds'), $p->{'body'}, $p->{'timestamp'}), $p->{'uuid'});
my $messenger = {
msg => $p->{'body'},
timestamp => $p->{'timestamp'},
type => 'message',
mail_contact => $p->{'contact'},
picker => {
projects => $p->{'project'},
accounts => $p->{'account'},
clubs => $p->{'club'},
teams => $p->{'team'},
communities => $p->{'community'},
people => $p->{'person'}
},
manager_file => $p->{'manager_file'}
};
my $message = encode_json $messenger;
foreach my $bti ( keys %{$gb::mailws->{$p->{'person'}}->{$p->{'account'}}->{$p->{'project'}}->{$p->{'team'}}->{$p->{'club'}}->{$p->{'community'}}} ) {
$gb::mailws->{$p->{'person'}}->{$p->{'account'}}->{$p->{'project'}}->{$p->{'team'}}->{$p->{'club'}}->{$p->{'community'}}->{$bti}->send($message);
}
}
}
if (scalar @{$m->{'decrypteds'}} > 0) {
$log->info('decrypteds here');
foreach my $d ( @{$m->{'decrypteds'}} ) {
my $dm = &subs::db_query('select * from mailbox where uuid = ?', $d)->hashes->[0];
$dm->{'body'} = &subs::note_decrypter($c->session('suds'),$dm->{'body'},$dm->{'ost'});
$dm->{'decrypted'} = 'yes';
my $content = $c->render_to_string(
template => 'mail/message',
'm' => $dm,
me => $me
);
&Websocket::send('mailbox', { type => 'mailbox_message', selector => '.mailbox_message[uuid="' . $dm->{'uuid'} . '"]', content => $content, browser_tab_id => $c->param('browser_tab_id') });
}
}
$mws->send($msg);
}
elsif ($m->{'type'} eq 'compose') {
my $message = $m->{'msg'};
$message->{'subject'} = &subs::note_encrypter($c->session('suds'), $message->{'subject'});
$message->{'body'} = &subs::note_encrypter($c->session('suds'), $message->{'body'});
if ($message->{'uuid'}) {
&subs::db_update('mailbox', {
email => $message->{'to'},
subject => $message->{'subject'},
body => $message->{'body'},
status => 'draft'
},
{
uuid => $message->{'uuid'}
});
}
else {
$message->{'uuid'} = &subs::random_string_creator(23);
&subs::db_insert('mailbox', {
email => $message->{'to'},
subject => $message->{'subject'},
body => $message->{'body'},
uuid => $message->{'uuid'},
status => 'draft'
});
}
&Websocket::send('tab', { console => '$(\'#email_compose_form\').attr(\'uuid\', \'' . $message->{'uuid'} . '\')' });
}
elsif ($m->{'type'} eq 'delete') {
if ($m->{'msg'}->{'uuid'}) {
&subs::db_delete('mailbox', { uuid => $m->{'msg'}->{'uuid'} });
my $message = &subs::db_select('mailbox', undef, { uuid => $m->{'msg'}->{'uuid'} })->hashes->[0];
&deletion_registration({ table => 'mailbox', uuid => $message->{'uuid'}, scope => 'single', server_time => $message->{'server_time'} });
&Websocket::send('tab', { console => '$(\'.mailbox_message[uuid="' . $m->{'msg'}->{'uuid'} . '\').remove();' });
}
}
elsif ($m->{'type'} eq 'message') {
$m->{'decrypted'} = 'yes';
foreach my $strip ( qw/msg manager_file/ ) {
my $hs = HTML::Strip->new();
$m->{$strip} = $hs->parse( $m->{$strip} );
$hs->eof;
}
my $manager_file = &manager_file_maker($name);
$m->{'manager_file'} = $manager_file;
if ($c->session('privilege') eq 'guest') {
$m->{'mail_contact'} = $c->session('ticket_uuid');
}
my $e_msg = &subs::note_encrypter($c->session('suds'),$m->{'msg'});
$m->{'body'} = $m->{'msg'};
my $picker = eval { return decode_json $m->{'picker'} } || {};
if ($m->{'mail_contact'}) { $picker = {} };
my ($db,$database,$sql) = &subs::database_grabber();
&subs::db_insert('mailbox', {
uuid => $m->{'uuid'},
timestamp => $m->{'timestamp'},
server_time => &subs::rightNow(),
body => $e_msg,
project => $picker->{'projects'},
account => $picker->{'accounts'},
club => $picker->{'clubs'},
team => $picker->{'teams'},
community => $picker->{'communities'},
manager_file => $m->{'manager_file'},
status => 'sent',
contact => $m->{'mail_contact'},
phone => $m->{'phone'},
email => $m->{'email'},
person => $picker->{'people'}
});
$m->{'envelope'} = $c->render_to_string(
template => 'mail/message',
'm' => $m,
'me' => $me
);
$msg = encode_json $m;
if ($m->{'phone'}) {
foreach my $bti ( keys %{$gb::mailws->{$m->{'phone'}}} ) {
$gb::mailws->{$m->{'phone'}}->{$bti}->send($msg);
}
&sms_message_send($m->{'phone'},$m->{'msg'});
}
elsif ($m->{'email'}) {
foreach my $bti ( keys %{$gb::mailws->{$m->{'email'}}} ) {
$gb::mailws->{$m->{'email'}}->{$bti}->send($msg);
}
}
elsif ($m->{'mail_contact'}) {
foreach my $bti ( keys %{$gb::mailws->{$m->{'mail_contact'}}} ) {
$gb::mailws->{$m->{'mail_contact'}}->{$bti}->send($msg);
}
if ($m->{'mail_contact'} eq 'pen') {
my $mesg = &subs::pen_message($m);
$mesg->{'envelope'} = $c->render_to_string(
template => 'mail/message',
'm' => $mesg,
'me' => $me
);
$mesg->{'type'} = 'message';
my $pmsg = encode_json $mesg;
foreach my $bti ( keys %{$gb::mailws->{$m->{'mail_contact'}}} ) {
$gb::mailws->{$m->{'mail_contact'}}->{$bti}->send($pmsg);
}
}
}
elsif ($c->session('privilege') eq 'guest') {
my $t_uuid = $c->session('ticket_uuid');
foreach my $bti ( keys %{$gb::mailws->{$t_uuid}} ) {
$gb::mailws->{$m->{'mail_contact'}}->{$bti}->send($msg);
}
}
else {
foreach my $bti ( keys %{$gb::mailws->{$picker->{'people'}}->{$picker->{'accounts'}}->{$picker->{'projects'}}->{$picker->{'teams'}}->{$picker->{'clubs'}}->{$picker->{'communities'}}} ) {
$gb::mailws->{$picker->{'people'}}->{$picker->{'accounts'}}->{$picker->{'projects'}}->{$picker->{'teams'}}->{$picker->{'clubs'}}->{$picker->{'communities'}}->{$bti}->send($msg);
}
}
if (&subs::setting_grabber({ app => 'mail', setting => 'lora_toggle' }) eq 'on') {
foreach my $device_type ( qw/watch teletype microcontroller/ ) {
my $chips = &subs::device_lister(&subs::rightNow(), $device_type, undef, 'all');
foreach my $watch ( @{$chips} ) {
if (eval {$watch->{'ip'} }) {
my $watch_port = $ENV{PORT_BELL};
my $ws_port = $ENV{PORT_MSG};
my $od = &subs::setting_grabber({ app => 'watch', setting => 'operator_door' });
my $op_d = eval { decode_json $od } || {};
my $secret = &subs::note_encrypter($op_d->{'__shutup'}->{'patience'}, $c->session('suds'));
$secret = `echo "$secret" | base64 -w 0`;
my $watch_home = 'http://' . $watch->{'ip'} . ':' . $config->{'port'} . '/chat_received?s=' . $secret . '×tamp=' . $m->{'timestamp'} . '&uuid=' . $m->{'uuid'};
my $ping = 'timeout .2 ping -c 1 ' . $watch->{'ip'};
my $ping_test = `$ping`;
if ($ping_test =~ /ttl/gi) {
Mojo::IOLoop->subprocess->run_p(sub {
my $ua = Mojo::UserAgent->new();
my $res = $ua->insecure(1)->get($watch_home)->result;
});
}
}
}
}
}
}
elsif ($m->{'type'} eq 'refresher') {
my ($db,$database,$sql) = &subs::database_grabber();
my $picker = eval { return decode_json $m->{'picker'} } || {};
my $q;
if ($m->{'phone'}) {
$q = &subs::db_query('select * from mailbox where timestamp > ? and phone = ? order by timestamp desc LIMIT 20', $m->{'last_message'}, $m->{'phone'});
}
elsif ($m->{'mail_contact'}) {
$q = &subs::db_query('select * from mailbox where timestamp > ? and contact = ? order by timestamp desc LIMIT 20', $m->{'last_message'}, $m->{'mail_contact'});
}
else {
$q = &subs::db_query('select * from mailbox where timestamp > ? and project=? and account =? and community = ? and club = ? and team = ? and person = ? order by timestamp desc LIMIT 20',
$m->{'last_message'}, $picker->{'projects'}, $picker->{'accounts'}, $picker->{'community'}, $picker->{'club'}, $picker->{'team'}, $picker->{'person'}
);
}
my $messaging = $q->hashes;
foreach my $mess ( @{$messaging} ) {
$mess->{'body'} = &subs::note_decrypter($c->session('suds'), $mess->{'body'}, $mess->{'ost'});
}
$messaging = encode_json { messages => $messaging, 'type' => 'refresher' };
$mws->send($messaging);
}
});
$c->on(finish => sub ($c, $code, $reason) {
$gb::mailws->{$browser_tab_id} = undef;
if ($c->param('phone') && $c->param('phone') ne 'null') {
$gb::mailws->{$c->param('phone')}->{$browser_tab_id} = undef;
}
elsif ($c->param('mail_contact') && $c->param('mail_contact') ne 'null') {
$gb::mailws->{$c->param('mail_contact')}->{$browser_tab_id} = undef;
}
elsif ($c->session('privilege') eq 'guest') {
$gb::mailws->{$c->session('ticket_uuid')}->{$browser_tab_id} = undef;
}
else {
$gb::mailws->{$picker->{'people'}}->{$picker->{'accounts'}}->{$picker->{'projects'}}->{$picker->{'teams'}}->{$picker->{'clubs'}}->{$picker->{'communities'}}->{$browser_tab_id} = undef;
}
});
};
get '/manager/remote_auth_test' => sub($c) {
my $appt = &subs::db_query('select server_time,app from appointments order by server_time DESC LIMIT 1')->hashes->[0];
my $ip = $c->tx->remote_address;
my $home_ip = $c->tx->local_address;
my $remote_domain = $c->param('domain') || $ip;
my $signatorial = $c->param('signatorial');
my $rm = &subs::db_select('remote_machines', ['ip','deletions','signatorial'], { ip => $remote_domain, signatorial => $signatorial })->hashes;
if (scalar @{$rm} > 0) {
if ($rm->[-1]->{'signatorial'}) {
my @domain = split '\.', $config->{'domain'};
shift @domain;
my $domain = join '.', @domain;
my $now = &subs::rightNow();
my $my_signatorial = &subs::signatorial_designer();
my @ws_auth = (
$ip, $my_signatorial
);
my $ws_joiner = join $universal_splitter, @ws_auth;
my $pa = &subs::random_string_creator(25);
my $ws_auth = &subs::encrypter($pa, $ws_joiner);
&subs::setting_setter({ app => '__president', setting => 'ws_pa', value => $pa});
my $json = {
server_time => $appt->{'server_time'},
app => $appt->{'app'},
port => $ENV{PORT_AHOY},
ws_port => $ENV{PORT_MSG},
signatorial => $my_signatorial,
now => $now,
me => $c->tx->local_address,
you => $c->tx->remote_address,
deletions => $rm->[-1]->{'deletions'},
fqdn => $config->{'domain'},
domain => $domain,
ws_auth => $ws_auth,
env => $ENV{PORT_ENV}
};
$c->render(json => $json);
my $deletions = eval { return decode_json $rm->[-1]->{'deletions'} } || [];
@{$deletions} = grep { $_->{'initialization'} + 60000 > &subs::rightNow() } @{$deletions};
$deletions = eval { return encode_json $deletions };
&subs::db_update('remote_machines', { deletions => $deletions }, { signatorial => $rm->[-1]->{'signatorial'} }) if eval { decode_json $rm->[-1]->{'deletions'} };
}
}
else {
$c->render(json => {});
}
};
sub remote_machine_reconnector($c) {
&subs::setting_setter({ app => '__president', setting => 'remote_connect_timer', value => &subs::rightNow() });
my $timestamp = &subs::rightNow();
my $browser_tab_id = $c->param('browser_tab_id');
my $browser_tab = $c->param('browser_tab');
my $ws_auth;
eval {
my $remote_machines = &subs::db_select('remote_machines', undef, { })->hashes;
foreach my $rm ( @{$remote_machines} ) {
my $ip = $rm->{'ip'};
my $ping = `timeout 1 ping -c 1 $ip`;
my $ping_test;
if ($ping !~ /ttl/) { $ping_test = 'no'; }
my $auuid = &subs::random_string_creator();
if ($ping =~ /ttl/) {
$rm = &remote_useragent_maker({ ip => $ip, signatorial => $rm->{'signatorial'}, rm => $rm });
my $manager = $rm->{'manager'};
my $port = $rm->{'port'};
$manager =~ s/:$port/:3000/gi;
if (!$rm->{'res'}) {
$ping_test = 'no';
}
if (!eval { return decode_json $rm->{'res'}->body }) {
$ping_test = 'no';
if ($rm->{'data'}->{'database'}) {
my $auuid = &subs::random_string_creator();
my $manager_file = &manager_file_maker($c->session('name'));
my $html = 'Reconnecting to ' . $ip . '
';
&Websocket::send('tab', { green => $html, uuid => $auuid });
my $password = $c->session('suds');
my $port = $rm->{'port'};
my $manager = $rm->{'manager'};
my $rdc = {
manager => $manager,
filename => $rm->{'data'}->{'database'},
timestamp => $timestamp,
ip => $ip,
password => $password,
name => $c->session('name'),
browser_tab_id => $browser_tab_id,
browser_tab => $browser_tab,
port => $rm->{'port'},
signatorial => $rm->{'signatorial'},
nic => $rm->{'nic'}
};
$rm->{'cookie'} = undef;
my $returner = &remote_device_connect($rdc);
if ($returner->{'body'}->{'signatorial'}) {
$ping_test = 'ok';
}
else {
$ping_test = 'no';
}
}
else { $ping_test = 'ok'; }
}
else {
my $rj = $rm->{'res'}->json;
my $appt = &subs::db_query('select server_time,app from appointments order by server_time DESC LIMIT 1')->hashes->[0];
if ($rj->{'fqdn'}) {
my @domain = split '\.', $rj->{'fqdn'};
my $subdomain = $domain[0];
if ($rj->{'ws_auth'}) {
$ws_auth = url_escape $rj->{'ws_auth'};
}
}
$rm->{'port'} = $rj->{'port'};
$rm->{'ws_port'} = $rj->{'ws_port'};
$ping_test = 'ok';
my $backup = &subs::db_query('select * from backups where reason=? and signatorial=? and recipient=? order by server_time DESC LIMIT 1',
'remote_upgraded',$rj->{'signatorial'},&subs::signatorial_designer())->hashes->[0];
if ($rj->{'deletions'}) {
&deletion_performer($rj->{'deletions'});
}
if ($device eq 'computer') {
my $diff = ($rj->{'now'} - &subs::rightNow());
if (abs $diff > 500) {
my $new_time = localtime($rj->{'now'} / 1000 )->strftime('%a %D %I:%M:%S%P');
my $update = `sudo date -s "$new_time"`;
}
}
if ($rj->{'server_time'} > $backup->{'server_time'}) {
my $whoami = `whoami`;
chomp $whoami;
my $hostname = `hostname`;
chomp $hostname;
my $gimme = $c->session('gimme') || $c->param('gimme');
my $params = {
timestamp => $rj->{'now'},
ip => $rm->{'ip'},
ssh_port => $rm->{'data'}->{'ssh_port'} || $config->{'ssh_port'},
database => $rm->{'data'}->{'database'},
remote_signatorial => $rj->{'signatorial'},
remote_device => $rm->{'data'}->{'device'},
gimme => $gimme
};
if ($ENV{PORT_ENV} eq 'production' && $rj->{'env'} eq 'production') {
# Mojo::IOLoop->subprocess->run_p(sub {
&remote_upgrade($c,$params);
# });
}
}
else {
}
}
}
else {
my $dev_info = &device_network_updater($rm);
}
&Websocket::send('tab', { green => ' ', 'close' => 'yes' });
if ($ping_test eq 'no') {
if ($rm->{'connection'} eq 'active') {
my $appts = &subs::db_select('appointments', undef, { app => &subs::unformat_name($rm->{'hostname'}), type => 'start' })->hashes;
foreach my $appt ( @{$appts} ) {
&appointment_writer($c, {
type => 'stop',
uuid => $appt->{'uuid'},
app => $appt->{'app'}
});
&subs::appt_header_printer({ app => $appt->{'app'} });
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $appt->{'app'} . '\',\'' . $appt->{'uuid'} .'\');'});
}
}
$rm->{'connection'} = 'inactive';
}
else {
$rm->{'connection'} = 'active';
}
&subs::db_update('remote_machines', { ws_auth => $ws_auth, ws_port => $rm->{'ws_port'}, port => $rm->{'port'}, connection => $rm->{'connection'} }, { ip => $rm->{'ip'}, signatorial => $rm->{'signatorial'} });
}
}
}
sub device_network_updater($data) {
my $nic = $data->{'nic'};
my $ifconfig = `ifconfig`;
my @ifconfig = grep { $_ =~ /$nic/ } split "\n\n", $ifconfig;
foreach my $if (@ifconfig) {
my @ifconfig_list = split "\n", $if;
my @ifconfig_inet = grep { $_ =~ /inet/ } @ifconfig_list;
}
}
websocket '/manager/ws' => sub ($c) {
my $ug = Data::UUID->new;
my $uuid = $ug->create_str();
my ($db,$database,$sql) = &subs::database_grabber();
my $app = $c->param('app');
my $remote_address = $c->tx->remote_address;
# $c->render(template => 'guest_layouts/denial') unless $app eq 'music' || $app eq 'server' || $app eq 'tab';
my $timestamp = $c->param('timestamp');
my $browser_tab_id = $c->param('browser_tab_id');
my $browser_tab = $c->param('browser_tab');
my $computer_name = &subs::unformat_name(&subs::setting_grabber({ app => 'me', setting => 'computer_name' }));
if ($c->param('browser_tab_id') eq '') {
$c->render('text' => 'no');
return;
}
my $browser_tab = $c->param('browser_tab');
my $user_agent = $c->param('user_agent') || $gb::user_agent;
my $server_time = &subs::rightNow();
my $hostname = `hostname`;
chomp($hostname);
my $connection_id = $c->tx;
$connection_id = $connection_id->connection;
my $init_data = {
browser_tab_id => $browser_tab_id,
browser_tab => $browser_tab,
db => $database,
'uuid' => $uuid,
timestamp => $timestamp,
connected => $timestamp,
server_time => $server_time,
type => 'connect',
app => $app,
hostname => $hostname,
connection_id => $connection_id,
user_agent => $user_agent,
random_string => &subs::random_string_creator(25),
href => $c->param('href'),
pathname => $c->param('pathname'),
ticket_uuid => $c->session('ticket_uuid')
};
if ($c->param('remote') eq 'yes') {
my @app = split /\@/, $app;
my $sapp = $app[0];
$gb::remote_ws->{$sapp}->{$browser_tab_id} = $c->tx;
}
else {
}
$gb::ws->{$app}->{$browser_tab_id} = $c->tx;
$gb::ws->{$app}->{$browser_tab_id}->{'privilege'} = $c->session('privilege');
my $tab_check = &subs::db_query('select * from websockets where browser_tab_id = ? and remote_address = ? and app = ?',$browser_tab_id, $remote_address, $app );
my $existing_websockets = $tab_check->hashes;
unless (scalar @{$existing_websockets} > 0) {
my $app = $c->session('app');
my $app_warranty = &subs::setting_grabber({ app => $app, setting => 'warranty' });
my $warranty = &subs::ago_calc($app_warranty || &subs::setting_grabber({ app => 'me', setting => 'warranty' }), $server_time);
$init_data->{'warranty'} = $warranty;
&subs::db_insert('websockets', $init_data);
}
else {
}
&Websocket::send($app, $init_data);
if ($c->param('app') eq 'music') {
my $appts = &subs::db_query('select * from appointments where source_uuid = ? and app = ? order by timestamp desc limit 30', $browser_tab, $computer_name)->hashes;
my $resolved = 0;
if (scalar @{$appts} > 0) {
foreach my $appt ( @{$appts } ) {
if ($appt->{'type'} eq 'stop') {
if (($appt->{'timestamp'} - $appt->{'duration'}) > &subs::rightNow() - 120000) {
$resolved = 1;
&subs::db_update('appointments', { server_time => &subs::rightNow(), type => 'start' }, { uuid => $appt->{'uuid'}, app => $appt->{'app'} });
&subs::intelligent_automation_toggle({ appt_uuid => $appt->{'uuid'}, app => $appt->{'app'}, 'state' => 'on', timestamp => $timestamp });
&subs::appt_header_printer({ app => $appt->{'app'} });
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $appt->{'app'} . '\',\'' . $appt->{'uuid'} .'\');'});
my $sources = &subs::db_select('appointments', undef, { source_uuid => $appt->{'uuid'} })->hashes;
foreach my $so ( @{$sources} ) {
push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes};
if ( $so->{'type'} eq 'stop' ) {
my $dur = $so->{'timestamp'} - $timestamp;
&subs::db_update('appointments', { stop_seen => 'yes', type => 'start', duration => $dur, server_time => $server_time }, { source_uuid => $so->{'source_uuid'}, uuid => $so->{'uuid'} });
&budget_runner($so->{'app'});
&subs::intelligent_automation_toggle({ appt_uuid => $so->{'uuid'}, app => $so->{'app'}, 'state' => 'on', timestamp => $timestamp });
&Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'});
}
}
}
}
elsif ($appt->{'type'} eq 'start') {
$resolved = 1;
}
}
}
if ($resolved == 0) {
my $jdata = encode_json { duty_time => $gb::duty_time };
my $data = {
app => $computer_name,
type => 'start',
data => $jdata,
timestamp => $timestamp,
source_uuid => $browser_tab
};
&appointment_writer($c,$data);
}
}
# $c->send({json => $init_data});
if ($app eq 'server') {
&Websocket::send('server', { magic_wand => $browser_tab_id, action => 'open', timestamp => $timestamp });
}
$c->on(message => sub ($ws, $msg) {
my $data = eval { return decode_json $msg };
my $app = $data->{'app'};
my $apper = $data->{'app'};
if ($app =~ /@/gi) {
my @app = split /\@/, $app;
$apper = $app[0];
}
my $remote_machines;
if ($data->{'type'} eq 'stayingAlive') {
my $server_time = &subs::rightNow();
$timestamp = $data->{'timestamp'};
my $connection = $ws->tx;
my $connection_id = $connection->connection;
my $local_address = $ws->tx->local_address;
my $remote_address = $ws->tx->remote_address;
if ($app eq 'music') {
$data->{'music_data'} = encode_json $data->{'music_data'} if $data->{'music_data'};
}
if ($app eq 'server') {
$data->{'jp_data'} = encode_json $data->{'jp_data'} if $data->{'jp_data'};
# my $remote_upgrade = &subs::setting_grabber({ app => '__president', setting => 'remote_upgrade' });
# my $remote_connect_timer = &subs::setting_grabber({ app => '__president', setting => 'remote_connect_timer' });
# if ($remote_connect_timer + (60 * 7 * 1000) < $timestamp) {
# &subs::setting_setter({ app => '__president', setting => 'remote_upgrade', value => '' });
# }
# if ($remote_upgrade ne 'running' && $remote_connect_timer + 30000 < $timestamp) {
# &remote_machine_reconnector($c);
# }
my $remote_machine_query = &subs::db_query('select * from remote_machines' );
$remote_machines = $remote_machine_query->hashes;
foreach my $rm ( @{$remote_machines} ) {
$rm->{'data'} = decode_json $rm->{'data'} if eval { decode_json $rm->{'data'} };
}
}
if ($app eq 'tab') {
if ($data->{'windows'}) {
my $windows = eval { return decode_json $data->{'windows'} } || [];
foreach my $w ( keys %{$windows} ) {
foreach my $set ( qw/scrollTop jopen/ ) {
if ($set eq 'jopen') {
$windows->{$w}->{$set} = encode_json $windows->{$w}->{$set};
}
&subs::setting_setter({ app => $windows->{$w}->{'app'}, setting => $set, value => $windows->{$w}->{$set} });
}
if ($windows->{$w}->{'headerUpdate'}) {
my $header = &subs::db_query('select * from cache where app = ? and context = ? and timestamp > ?', $windows->{$w}->{'app'}, 'header', $windows->{$w}->{'headerUpdate'})->hashes;
foreach my $head ( @{$header} ) {
my $data = decode_json $head->{'data'};
&Websocket::send($app, { type => 'header', app => $windows->{$w}->{'app'}, timestamp => $head->{'timestamp'}, header => $data->{'header'} });
}
}
}
}
}
&subs::db_update('websockets', {
timestamp => $timestamp,
server_time => $server_time,
type => $data->{'type'},
connection_id => $connection_id,
local_address => $local_address,
remote_address => $remote_address,
windows => $data->{'windows'},
music_data => $data->{'music_data'},
jp_data => $data->{'jp_data'},
href => $data->{'href'},
pathname => $data->{'pathname'}
}, {
browser_tab_id => $browser_tab_id,
app => $data->{'app'}
});
if ($data->{'debriefer'}) {
if ($c->session('ticket_uuid')) {
&subs::db_query('update tickets set debriefer = ? where uuid = ?', $data->{'debriefer'}, $c->session('ticket_uuid'));
}
else {
my $hostname = `hostname`;
chomp($hostname);
&subs::setting_setter({ app => '__DEBRIEFING__', setting => $hostname, value => $data->{'debriefer'} });
}
}
my $community = &subs::db_query('select * from websockets where ( app = ? or app like ? ) and type = ? and server_time >= ? order by server_time DESC',$app, $app . '@%', 'stayingAlive',$server_time - 5000);
my $neighbours = $community->hashes;
foreach my $n ( @{$neighbours} ) {
my $neighbour_windows = $n->{'windows'};
my $neighbourhood = eval { return decode_json $n->{'windows'} } || {};
$n->{'user_agent'} = &subs::abbreviate_name($n->{'user_agent'});
foreach my $nw ( keys %{$neighbourhood} ) {
$neighbourhood->{$nw}->{'formatted_name'} = &subs::format_name($neighbourhood->{$nw}->{'app'});
$neighbourhood->{$nw}->{'shorthand_name'} = &subs::shorthand_name($neighbourhood->{$nw}->{'formatted_name'});
}
$n->{'windows'} = encode_json $neighbourhood;
}
my $return_data = {
browser_tab_id => $browser_tab_id,
browser_tab => $browser_tab,
'uuid' => $uuid,
timestamp => $timestamp,
app => $data->{'app'},
neighbours => $neighbours,
from => $hostname,
connection_id => $connection_id,
user_agent => $user_agent,
type => $data->{'type'},
local_address => $local_address,
remote_address => $remote_address,
input => $data->{'input'},
remote => $remote_machines
};
$return_data->{'template'} = $c->render_to_string(
template => 'websockets/' . $app,
ws => $return_data
) if -e './templates/websockets/' . $apper . '.html.ep';
&Websocket::send($app,$return_data);
}
elsif ($data->{'type'} eq 'synth' && $app eq 'music') {
my $freq = $data->{'freq'};
my $waveform = $data->{'waveform'};
my $length = $data->{'length'};
Mojo::IOLoop->subprocess->run_p(sub {
`play "|sox -n -p synth $length $waveform $freq " &`;
});
}
elsif ($data->{'method'} eq 'playerCache') {
&subs::cache_set({ app => 'music', context => 'player' }, $data);
}
elsif ($data->{'method'} eq 'transmitter') {
$data->{'browser_tab_id'} = $browser_tab_id;
&subs::music_transmitter($c, $data);
}
else {
$data->{'not_me'} = 1;
$data->{'browser_tab_id'} = $browser_tab_id;
&Websocket::send($app, $data);
}
});
$c->on(finish => sub ($c,$code,$reason) {
&subs::db_update('websockets', { 'type' => 'closed'}, { app => $app, browser_tab_id => $browser_tab_id });
delete $gb::ws->{$app}->{$browser_tab_id};
&Websocket::send('server', { magic_wand => $browser_tab_id, action => 'closed', timestamp => $timestamp });
if ($app eq 'music') {
my $appts = &subs::db_query('select * from appointments where source_uuid = ? and app = ? and type = ? order by timestamp desc limit 30', $browser_tab, $computer_name,'start')->hashes;
foreach my $appt ( @{$appts} ) {
&appointment_writer($c, {
type => 'stop',
uuid => $appt->{'uuid'},
app => $appt->{'app'}
});
&subs::appt_header_printer({ app => $appt->{'app'} });
&Websocket::send('server', { console => 'appointmentDetailGrabber(\'' . $appt->{'app'} . '\',\'' . $appt->{'uuid'} .'\');'});
}
}
});
unless (1 == 0 && $c->param('remote') eq 'yes') {
my $remote_machine_query = &subs::db_query('select * from remote_machines where connection=?','active' );
my $remote_machines = $remote_machine_query->hashes;
foreach my $rm ( @{$remote_machines} ) {
my $id = '';
my @ip = split /\./, $rm->{'ip'};
if ($rm->{'ip'} =~ /[A-Za-z]/gi) {
$id = $ip[0];
}
else {
$id = $ip[-1];
}
my $command = { console => 'websocketStart(\''. $app . '@' . $id . '\',\'wss://' . $rm->{'ip'} . ':' . $rm->{'ws_port'} . '/manager/ws?remote=yes&app=' . $app . '@' . $id . '&browser_tab_id=' . $rm->{'signatorial'} . '×tamp=' . &subs::rightNow() . '&ws_auth=' . $rm->{'ws_auth'} . '\');' };
#&Websocket::send('server', $command);# if !grep { $_ eq $app } qw/music server tab/;
}
}
};
post 'manager/ws/remote_control' => sub($c) {
my $destination = $c->param('destination');
my $value = $c->param('value');
my $app = &subs::unformat_name($c->param('app'));
my $control = $c->param('control');
&Websocket::send($app, {
value => $value,
app => $app,
control => $control,
destination => $destination,
type => 'remote_control'
});
$c->render(text => 'ok');
};
get '/manager/remote_refresh' => sub ($c) {
my $bti = $c->param('bti');
my $browser_tab_id = $c->param('browser_tab_id');
my $timestamp = $c->param('timestamp');
&Websocket::send('server', { console => 'location.reload()', origin => $browser_tab_id, destination => $bti, timestamp => $timestamp });
};
sub paperRoute($msg) {
my ($db,$database,$sql) = &subs::database_grabber();
my $original_msg = $msg;
if ( eval { encode_json $msg }) {
my $m = encode_json $msg;
if (eval { $sql->db } && $sql->dsn !~ /:$/) {
my $server_time = &subs::rightNow();
my $uuid = &subs::random_string_creator(20);
&subs::db_insert('websocket_messages', {
timestamp => $original_msg->{'timestamp'},
message => $m,
server_time => $server_time,
uuid => $uuid,
sent_count => 0,
environment => 'papers'
});
}
}
}
if ($ENV{PURPOSE} eq 'websocket' || ($ENV{PORT_ENV} eq 'development' && $ENV{PURPOSE} eq 'main')) {
my $db_running = 0;
my $id = Mojo::IOLoop->recurring(.4 => sub {
if ($db_running == 0) {
$db_running = 1;
my $returner;
my ($db,$database,$sql) = &subs::database_grabber();
if ($db) {
my $wm = &subs::db_query('select * from websocket_messages');
my $ws_messages = $wm->hashes;
foreach my $wsm ( @{$ws_messages} ) {
my $return_msg = &websocket_sender($wsm);
if ($wsm->{'uuid'}) {
if (!grep { $_->{'uuid'} ne $wsm->{'uuid'} } @{$return_msg->{'save'}}) {
&subs::db_query('delete from websocket_messages where uuid=?',$wsm->{'uuid'});
}
}
else {
&subs::db_query('delete from websocket_messages where timestamp = ?', $wsm->{'timestamp'});
}
}
}
$db_running = 0;
}
});
}
sub websocket_sender($wsm) {
my $returner;
my $return_msg = { save => [] };
if ($wsm->{'environment'} eq 'papers') {
foreach my $subscriber ( keys %{$gb::paperboy} ) {
$gb::paperboy->{$subscriber}->send($wsm->{'message'});
}
}
else {
my $original_msg = eval { return decode_json $wsm->{'message'} } || {};
#return unless $original_msg->{'app'};
my $msg = $original_msg;
my $app = $wsm->{'app'};
my $server_time = $wsm->{'server_time'};
my $timestamp = $wsm->{'timestamp'};
my $count = 0;
foreach my $ws ( $gb::ws, $gb::remote_ws ) {
if ($count != 0) {
my @app = split /\@/, $app;
$app = $app[0];
}
else {
}
if ($original_msg->{'remote_only'}) {
if ($original_msg->{'remote_only'} eq 'yes' && $count == 0) {
next;
}
}
if ( $original_msg->{'destination'}) {
if ($ws->{$app}->{$wsm->{'destination'}}) {
$ws->{$app}->{$wsm->{'destination'}}->send($wsm->{'message'});
}
elsif ($wsm->{'server_time'} > &subs::rightNow() - 10000) {
push @{$return_msg->{'save'}}, $wsm;
}
}
elsif ($original_msg->{'not_me'}) {
foreach my $w ( keys %{$ws->{$app}} ) {
if ($ws->{$app}->{$w} && $w ne $original_msg->{'browser_tab_id'}) {
if ($msg->{'role'} && $msg->{'role'} ne 'all') {
if ($msg->{'role'} ne $ws->{$app}->{$w}->{'privilege'}) {
next;
}
}
$returner = $ws->{$app}->{$w}->send($wsm->{'message'});
}
}
}
else {
foreach my $w ( keys %{$ws->{$app}}) {
if ($ws->{$app}->{$w}) {
if ($msg->{'role'} && $msg->{'role'} ne 'all') {
if ($msg->{'role'} ne $ws->{$app}->{$w}->{'privilege'}) {
next;
}
}
$returner = $ws->{$app}->{$w}->send($wsm->{'message'});
}
}
}
}
$count++;
}
return $return_msg;
}
get '/manager/ws_close' => sub($c) {
my $websocket = &subs::db_select('websockets', undef, { app => $c->param('app'), browser_tab_id => $c->param('browser_tab_id') })->hash;
unless ($websocket->{'room'}) {
&subs::db_delete('websockets', { app => $c->param('app'), browser_tab_id => $c->param('browser_tab_id') });
}
$c->render('text' => 'ok');
};
sub websocketClose($app) {
#soon
}
if ($ENV{PURPOSE} ne "alarm") {
app->sessions->samesite('lax');
$ENV{MOJO_MAX_MESSAGE_SIZE} = 1023423423473741824;
app->renderer->cache->max_keys(0);
#app->sessions->encrypted(1);
app->secrets($gb::secret_maker);
app->sessions->cookie_name($ENV{'cookie_name'});
app->start;
}
else {
1;
}