#!/usr/bin/perl use strict; use warnings; package Alarm; use Mojolicious::Lite; use List::Util qw(shuffle); use Mojo::Util qw/html_unescape term_escape/; use Time::Duration; use Date::Parse; use Time::Piece; use Crypt::Simple; use File::Slurp; use Mojo::JSON qw(decode_json encode_json); use Data::Dumper; use Time::HiRes qw(gettimeofday time); require "./gb.pl"; require "./subroutines.pl"; require "./Manager.pl"; require "./Websocket.pl"; my $config_file = read_file('./config.json'); my $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 $device = &subs::device_setter(); my $last_moment = &subs::rightNow(); my $last_paper_moment = &subs::rightNow(); sub alarm_clock() { my ($dber,$dot,$sql) = &subs::database_grabber(); return unless $dber; my $timestamp = &subs::rightNow(); $last_moment = &subs::rightNow(); my $query = &subs::db_query('select * from appointments where (timestamp <= ? and seen is null) or ((type = ? or type = ? or type = ? or type=? or type = ?) and stop_timestamp is not null and stop_timestamp <= ? and stop_seen is null ) order by timestamp', $timestamp, 'start','record','video','audio','screen',$timestamp); my $alarm = $query->hashes; my $duty_watch = &subs::db_query('select * from appointments where duties is not null and next_duty <= ? and next_duty is not null', $timestamp)->hashes; foreach my $dw ( @{$duty_watch} ) { my $duties = eval { return decode_json $dw->{'duties'} } || []; my @seen_duties; foreach my $duty ( @{$duties} ) { my $jduty = encode_json $duty; if ($duty->{'timestamp'} <= $timestamp) { push @{$alarm}, { app => $dw->{'app'}, type => $duty->{'duty'}, uuid => $dw->{'uuid'}, data => $jduty, timestamp => $dw->{'timestamp'} }; push @seen_duties, $duty->{'duuid'}; } } foreach my $sd ( @seen_duties ) { @{$duties} = grep { $_->{'duuid'} && $_->{'duuid'} ne $sd } @{$duties}; } my $next_duty = $duties->[0]->{'timestamp'}; @{$duties} = grep { $_->{'duuid'} } @{$duties}; @{$duties} = sort { $a->{'timestamp'} <=> $b->{'timestamp'} } @{$duties}; my $jduties = encode_json $duties; if (scalar @{$duties} == 0) { $jduties = undef; } &subs::db_update('appointments', { duties => $jduties, next_duty => $next_duty, server_time => &subs::rightNow() }, { app => $dw->{'app'}, uuid => $dw->{'uuid'} }); } if (scalar @{$alarm} > 0) { my $interval = 'second'; my $default_warranty = &subs::setting_grabber({ app => 'me', setting => 'warranty' }) || '-10d'; my $warranty = &subs::ago_calc($default_warranty, $timestamp); my $t = &{$subs::time_subs->{$interval}}($timestamp); my $t1 = ($timestamp - $t); foreach my $a ( @{$alarm} ) { &subs::db_query('update appointments set seen = ? where uuid=?', 'yes',$a->{'uuid'}); &subs::cache_delete({ app => $a->{'app'}, context => 'template' }); my $type = $a->{'type'}; if ($a->{'stop_timestamp'} && $a->{'stop_timestamp'} <= $timestamp && grep { $a->{'type'} eq $_ } qw/start video audio screen record/) { if ($a->{'type'} eq 'start' || $a->{'type'} eq 'record') { if ($a->{'type'} eq 'record') { my $data = eval { return decode_json $a->{'data'} } || {}; my $recording_type = &subs::setting_grabber({ app => $a->{'app'}, setting => 'record' }) || 'system'; if ($data->{'recorder'} eq 'security') { &Manager::record_video_stop({ app => $a->{'app'}, uuid => $a->{'uuid'}, timestamp => $a->{'timestamp'} }); } elsif ($data->{'recorder'} eq 'system') { &Manager::record_audio_stop({ app => $a->{'app'}, uuid => $a->{'uuid'}, timestamp => $a->{'timestamp'} }); } else { &Websocket::send('music', { console => 'jpStop(\'' . $a->{'app'} . '\',\'' . $data->{'recorder'} . '\',\'' . $a->{'uuid'} . '\');' }); } } else { &subs::db_query('update appointments set seen = ?,type=?, stop_seen=? where uuid=?', 'yes','stop', 'yes',$a->{'uuid'}); } &subs::intelligent_automation_toggle({ app => $a->{'app'}, 'state' => 'off', timestamp => $timestamp }); $type = 'stop'; my $sources = &subs::db_select('appointments', undef, { source_uuid => $a->{'uuid'} })->hashes; foreach my $so ( @{$sources} ) { push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes}; if ( $so->{'type'} eq 'start' && (!$so->{'stop_timestamp'} || $so->{'stop_timestamp'} <= $timestamp) ) { my $dur = $so->{'timestamp'} - $timestamp; &subs::db_update('appointments', { stop_seen => 'yes', type => 'stop', duration => $dur }, { 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 => $timestamp }); &Websocket::send('tab', { console => 'appointmentDetailGrabber(\'' . $so->{'app'} . '\',\'' . $so->{'uuid'} .'\');'}); } } } else { &subs::db_query('update appointments set seen = ?, stop_seen=? where uuid=?', 'yes', 'yes',$a->{'uuid'}); } &Websocket::send('tab', { console => 'appointmentDetailGrabber("' . $a->{'app'} . '","' . $a->{'uuid'} .'");' }); } elsif ($a->{'type'} eq 'start' || $a->{'type'} eq 'record') { &subs::intelligent_automation_toggle({ app => $a->{'app'}, 'state' => 'on', timestamp => $a->{'timestamp'} }); my $sources = &subs::db_select('appointments', undef, { source_uuid => $a->{'uuid'} })->hashes; foreach my $so ( @{$sources} ) { push @{$sources}, @{&subs::db_select('appointments', undef, { source_uuid => $so->{'uuid'} })->hashes}; if ( $so->{'type'} eq 'start' && (!$so->{'stop_timestamp'} || $so->{'stop_timestamp'} <= $timestamp) ) { &subs::db_update('appointments', { seen => 'yes' }, { 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'} .'\');'}); } } if ($a->{'type'} eq 'record') { my $recording_type = &subs::setting_grabber({ app => $a->{'app'}, setting => 'record' }) || 'system'; my $data = eval { return decode_json $a->{'data'} } || {}; if ($data->{'recorder'} eq 'security') { &Manager::record_video({ app => $a->{'app'}, uuid => $a->{'uuid'}, timestamp => $a->{'timestamp'} }); } elsif ($data->{'recorder'} eq 'system') { &Manager::record_audio({ app => $a->{'app'}, uuid => $a->{'uuid'}, timestamp => $a->{'timestamp'} }); } elsif ($data->{'recorder'} eq 'screen') { &Websocket::send('music', { console => 'jpScreen(\'' . $a->{'app'} . '\',\'' . $a->{'uuid'} . '\');' }); } else { &Websocket::send('music', { console => 'jpStart(\'' . $a->{'app'} . '\',\'' . $data->{'recorder'} . '\',\'' . $a->{'uuid'} . '\');' }); } } } elsif ($a->{'type'} eq 'stop' || $a->{'type'} eq 'cancel') { &subs::intelligent_automation_toggle({ app => $a->{'app'}, 'state' => 'off', timestamp => $timestamp }); } elsif ($a->{'type'} eq 'image') { my $data = decode_json $a->{'data'}; my $c = app->build_controller; $c->stash('app' => $a->{'app'}); $c->session('timestamp' => $timestamp); my ($file,$ocr) = &Manager::take_picture($c,{ app => $a->{'app'}, timestamp => $timestamp, camera => $data->{'camera'}, uuid => $a->{'uuid'} }); } elsif ($a->{'type'} eq 'scan') { my $scandata = decode_json $a->{'data'}; my $c = app->build_controller; $c->stash('app' => $a->{'app'}); $c->stash('timestamp' => $a->{'timestamp'}); my $file = &Manager::scan($c, $scandata); } &subs::appt_header_printer({ app => $a->{'app'} }); my $settings = &subs::settings_grabber({ app => $a->{'app'} }) || {}; my $name = &subs::format_name($a->{'app'}); my $app = &subs::unformat_name($a->{'app'}); my $account = &subs::format_name($a->{'account'}); if ($settings->{'notification'} && $settings->{'notification'} eq 'on') { &Manager::notification_sender({ app => $app, role => 'all', uuid => $a->{'uuid'}, type => $type, settings => $settings, sound => 'crystal.mp3', title => $name, },$dot); } if ($a->{'type'} =~ /command|kill|record/) { my $command = $settings->{$a->{'type'}}; my $resulter = &subs::run_command($app,$command); if ($a->{'type'} eq 'command') { &subs::setting_setter({ app => $app, setting => 'toggle', value => 'on' }); } elsif ($a->{'type'} eq 'kill') { &subs::setting_setter({ app => $app, setting => 'toggle', value => 'off' }); } } } } my $ticket_query = &subs::db_query('select count(*) from tickets where status = ? and warranty < ?', 'active', $timestamp); my $t_count = $ticket_query->text; if ($t_count > 0) { my $ticket_update_query = &subs::db_query('update tickets set status = ? where status = ? and warranty < ?', 'expired', 'active', $timestamp); my $msg = { app => 'box_office', console => 'ticket_list()' }; my $server_time = &subs::rightNow(); &Websocket::send('server', $msg); } my $warranty_query = &subs::db_query('select * from appointments where warranty < ?',$timestamp); my $haircut = $warranty_query->hashes; foreach my $h ( @{$haircut} ) { foreach my $t ( qw/appointments/ ) { &Manager::delete_app($h->{'app'}, $h->{'uuid'},$h->{'server_time'},'alarm runner'); #&subs::db_delete($t, { app => $h->{'app'}, uuid => $h->{'uuid'} }); } if (grep { $_ ne $h->{'app'} } qw/misc customs music __president me/) { &subs::vacuum($h->{'app'}); } } my $backups = [];#&subs::db_query('select * from backups where warranty < ?', $timestamp)->hashes; foreach my $b ( @{$backups} ) { if (-e $b->{'destination'}) { my $commander = 'shred -u ' . $b->{'destination'}; # `$commander`; } #&subs::db_delete('backups', { uuid => $b->{'uuid'} }); } my $paper_q = &subs::db_query('select * from magazine where status=? and timestamp >= ? and timestamp <= ? and warranty >=?', 'publish',$last_paper_moment, $timestamp,$timestamp); my $papers = $paper_q->hashes; foreach my $paper ( @{$papers} ) { my $c = app->build_controller; $paper->{'art'} = $c->render_to_string(template => 'article', art => $paper); &Manager::paperRoute($paper); } $last_paper_moment = &subs::rightNow(); &subs::db_query('delete from magazine where warranty < ?', $timestamp); &subs::db_query('delete from continent where warranty < ?', $timestamp); &subs::db_query('delete from websites where warranty < ?', $timestamp); &subs::db_query('delete from cache where warranty < ?', $timestamp); my $websocks = &subs::db_query('select * from websockets where warranty < ?', $timestamp); foreach my $webs (@{$websocks->hashes}) { my $art_query = &subs::db_query('delete from drawings where browser_tab_id = ?', $webs->{'browser_tab_id'}); my $del_query = &subs::db_query('delete from websockets where browser_tab_id = ?', $webs->{'browser_tab_id'}); } } sub budget_watcher() { my ($db,$database,$sql) = &subs::database_grabber('memory'); unless (&subs::setting_grabber({ app => 'me', setting => 'budget_alarm', device => $device }) eq 'on') { return 0; } my $w_time = &subs::rightNow() + &subs::time_abbrev_translator('1m',&subs::rightNow()); my $budgets = &subs::db_query('select distinct(app) as app,* from settings where setting = ? and device = ? and value is not null','budget', $device)->hashes; my $settings; foreach my $b ( @{$budgets} ) { my $app = $b->{'app'}; my @buds = split /,/, $b->{'value'}; my $scope; $settings->{$app} = &subs::settings_grabber({ app => $app }) unless $settings->{$app}; 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]; if (1) { my $budget = &Manager::budget_calculator({ app => $app, circumstance => $circumstance, scope => $scope, budget => $bud, settings => $settings->{$app} }); if ($budget->{'is_scope'} && $circumstance eq $budget->{'circumstance'}) { my $server_time = &subs::rightNow(); $budget->{'timestamp'} = &subs::rightNow(); &subs::cache_delete({ app => $app, context => 'template' }); &subs::cache_set({ app => $app, context => 'budget', subcontext => $circumstance }, $budget); if ($cache_budget->{'status'} ne $budget->{'status'}) { my $websockets = &subs::db_query('select * from websockets where app = ? and windows like ? and server_time > ? and windows is not null order by timestamp DESC', 'tab', '%app":"' . $app . '%', $server_time - 5000)->hashes; if (scalar @{$websockets} > 0) { my $msg = { app => $app, type => 'budget', budget => { colour => $budget->{'colour'}, circumstance => $budget->{'circumstance'}, } }; &Websocket::send('tab', $msg); &subs::appt_header_printer({ app => $app }); } my $message = &subs::format_name($app) . ' is ' . $budget->{'status'} . ' for ' . $circumstance . ': ' . $budget->{'formatted_value'} . '/' . $budget->{'formatted_budgeted'}; if (&subs::setting_grabber({ app => $app, setting => 'notification', device => $device }) eq 'on') { &Manager::notification_sender({ app => $app, role => 'all', title => &subs::format_name($app), synth => $budget->{'synth'}, words => $app, message => $message, image => "/images/decipherable/chart.png", type => 'budget' },$database); } #&Manager::budget_autocalc({ # app => $app, # circumstance => $circumstance, #}); } } } } } } return 0; } sub housekeeping() { my ($db,$database,$sql) = &subs::database_grabber(); my $server_time = &subs::rightNow(); my $settings = &subs::settings_grabber({ app => '__president', device => $device }); my @cache_folders = split /\n/, $settings->{'cache_folders'}; foreach my $cf (@cache_folders) { if ($cf ne '/' && $cf ne &subs::home('~/') && $cf =~ /[a-z0-9A-Z]/) { my $folder = &subs::home($cf); my $doomed = `ls -a $cf`; my @doomed = split /\n/, $doomed; foreach my $doom ( @doomed ) { my $rip = $folder . '/' . $doom; unless ($doom eq '.' || $doom eq '..') { # my $success = `shred -u $rip`; } } } } my $expiration = &subs::ago_calc('-1h', $server_time); my $websockets = &subs::db_query('delete from websockets where server_time < ? and room is not null', $expiration); return 0; } sub task_checker() { my $server_time = &subs::rightNow(); my $tasks = &subs::db_query('select app from settings where setting = ? and value is not null','tasks')->hashes; foreach my $task ( @{$tasks} ) { my $app = $task->{'app'}; my $taskskis = &subs::task_grabber($app); my $websockets = &subs::db_query('select * from websockets where app = ? and windows like ? and server_time > ? and windows is not null order by timestamp DESC', 'tab', '%app":"' . $app . '%', $server_time - 5000)->hashes; if (scalar @{$websockets} > 0) { my $msg = { app => $app, type => 'html', selector => '.re_tasks[app="' . $app . '"]', content => $taskskis->{'html'} }; &Websocket::send('server', $msg); } } return 0; } 1;