package ONO::Cron::CronSync::Bot;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
use strict;
use ONO::IO;
use ONO::DB;
use ONO::Lib::Basic;
use ONO::FW::User::Bot;
use ONO::FW::User::Stats;
use ONO::FW::Media::Books::BookMaker::App::Dir;
use ONO::FW::Media::Books::BookMaker::App::Generate;
use ONO::ToolBox::SendMail;
use ONO::ToolBox::Docs;
use ONO::Lib::Mail::ToolBox;
use ONO::Lib::Audio::ToolBox;
use ONO::Lib::Video::ToolBox;
use ONO::Cron::CronSync::ToolBox;
###############################################################################
# ONO
###############################################################################
#: Bot related services for ONO's CronSync service.
#: Note that most of these features may be phased out, starting in 2026.
sub run {
my (
$self,
$CRON_DIR,
$job,
$data_ref,
$TYPE_ref,
$vars_ref,
$vpath,
$sec,$min,$hour,
$mday,$mon,$year,
$wday,$yday,
$timestamp,
$switches,
) = @_;
#: Execution logic.
my %data = %$data_ref;
my %TYPE = %$TYPE_ref;
my %vars = %$vars_ref;
my ($DATA,$MAIL);
if (ONO::IO->exists("etc/cronsync/custom_bot_overload_protection.txt")) {
if (ONO::IO->sysload() > ONO::IO->load("etc/cronsync/custom_bot_overload_protection.txt")) {
$data{'type'} = "bot_overload";
$DATA .= ONO::Cron::CronSync::ToolBox->print("- ABORT: SysLoad higher than value defined in etc/cronsync/custom_bot_overload_protection.txt",$switches);
}
} else {
if (!ONO::IO->sysload(34)) {
$data{'type'} = "bot_overload";
$DATA .= ONO::Cron::CronSync::ToolBox->print("- ABORT: SysLoad higher than 33%, which is not allowed for BOT type jobs",$switches);
}
}
if ($data{'type'} eq "bot_custom_cron") {
if ($data{'bot_community'} =~ /[a-z0-9]/ && ONO::IO->exists("cgi-bin/local/perl/$data{'bot_community'}/cron/cron.pl")) {
ONO::IO->exec("$vpath/cgi-bin/local/perl/$data{'bot_community'}/cron/cron.pl");
}
}
if ($data{'type'} eq "bot_update_stats") {
if ($data{'bot_community'} =~ /[a-z0-9]/) {
my %setup;
my $db = ONO::DB->connect($data{'bot_community'});
$setup{'cache_store'} = 1;
$setup{'users_global_multiplier'} = 1;
if ($data{'bot_update_stats_users_global_multiplier'}) {
$setup{'users_global_multiplier'} = $data{'bot_update_stats_users_global_multiplier'};
}
if ($data{'bot_update_stats_users_global_minlevel'}) {
$setup{'users_global_minlevel'} = $data{'bot_update_stats_users_global_minlevel'};
}
if ($data{'bot_update_stats_users_global_maxlevel'}) {
$setup{'users_global_maxlevel'} = $data{'bot_update_stats_users_global_maxlevel'};
}
ONO::FW::User::Stats->update($db,$data{'bot_community'},\%setup);
if ($data{'bot_update_stats_import_key'}) {
for (my $s = 1; $s < 5; $s++) {
if ($data{"bot_update_stats_import_site_$s"} =~ /^http/) {
my $SITE = $data{"bot_update_stats_import_site_$s"};
$SITE = lc $SITE;
$SITE =~ s~^(http|https)://~~;
$SITE =~ s~/(.*)$~~;
$SITE =~ s~[^a-z]~~g;
if ($SITE) {
my $CURL = ONO::IO->curl(qq~$data{"bot_update_stats_import_site_$s"}?mode=ono_community_statistics_export&key=$data{'bot_update_stats_import_key'}~);
if ($CURL =~ /^cache_timestamp/) {
ONO::IO->mkpath("var/community/$data{'bot_community'}/statistics/subsites");
ONO::IO->store("var/community/$data{'bot_community'}/statistics/subsites/$SITE.txt",$CURL);
}
}
}
}
}
}
}
if ($data{'type'} eq "bot_microblog") {
if ($data{'bot_community'} =~ /[a-z0-9]/) {
# -a always execute everything (only recommended for debugging)
# -c kick off the custom platform bot at the end of the script
my $switches;
if (ONO::IO->devstation) {
$switches .= "a";
}
if ($data{'bot_custombot'}) {
$switches .= "c";
}
$DATA .= ONO::FW::User::Bot->run(ONO::DB->connect($data{'bot_community'}),$data{'bot_community'},$vpath,$switches,\%vars);
}
}
if ($data{'type'} eq "bot_mailnews") {
# first we'll need to update daysonline
if ($data{'bot_mailnews_daysonlineinc'} && $data{'bot_community'}) {
my $db = ONO::DB->connect($data{'bot_community'});
if ($data{'bot_mailnews_daysonlineinc_hour'} == $hour && $data{'bot_mailnews_daysonlineinc_min'} == $min) {
ONO::DB->command($db,"UPDATE $data{'bot_community'}_community_status SET daysonline = '0' WHERE daysonline IS NULL;");
ONO::DB->command($db,"UPDATE $data{'bot_community'}_community_status SET daysonline = daysonline + 1 WHERE status = '1';");
}
}
# then we'll see if we could / should send out mails
if ($data{'bot_mailnews_sendmail'} && $data{'bot_community'}) {
my $db = ONO::DB->connect($data{'bot_community'});
# not implemented yet
}
}
if ($data{'type'} eq "bot_mailer") {
my $REPORT = "Starting bot_mailer for community $data{'bot_community'} at $mday/$mon/$year \@ $hour:$min:$sec...\n";
my $db = ONO::DB->connect($data{'bot_community'});
# main 1/2: check bounces
my $bounces;
foreach my $file (ONO::IO->dir("var/tmp/bouncedmails")) {
if ($file !~ /^\./ && $file =~ /[A-Za-z0-9]/ && $bounces < 100) {
$REPORT .= "Handling bounced mail: $file ";
my ($mail,$user,$status);
foreach my $line (ONO::IO->list("var/tmp/bouncedmails/$file")) {
if (!$mail) {
$line =~ s~(\n|\r|\t)~~g;
if ($line =~ /To: (.*?)$/) {
$mail = $1;
}
}
}
$mail = ONO::Lib::Basic->cleanmail($mail);
if (ONO::Lib::Basic->valid_email($mail)) {
$bounces++;
$REPORT .= ", mail = '$mail' ($bounces)...\n";
# do we know this user?
foreach my $line (ONO::DB->select($db,"$data{'bot_community'}_community_users","email = '$mail'")) {
my @col = ONO::DB->readcols($line);
$user = $col[0];
}
my $count = ONO::DB->count($db,"$data{'bot_community'}_community_mailbounce","bounced_email = '$mail'")+1;
my $status = $count;
ONO::DB->command(
$db,
qq~INSERT INTO $data{'bot_community'}_community_mailbounce (username,bounced_email,bounced_date,bounced_timestamp,bounced_total,bounced_status) VALUES
('$user','$mail','$year$mon$mday','$timestamp','$count','$status');~,
);
} else {
$REPORT .= ", unknown (abort)\n";
}
ONO::IO->rm("var/tmp/bouncedmails/$file");
}
}
# main 2/2: actually send mails
my ($SITE,$DOMAIN) = ONO::Cron::CronSync::ToolBox->get_site();
my %conf = &loadconf("","var/community/$data{'bot_community'}/bot/config.txt");
if ($conf{'domain'}) {
$DOMAIN = $conf{'domain'};
}
my (%cache,%domain_rule,@domain_rules,$default_lang);
if ($conf{'default_lang'}) {
$default_lang = $conf{'default_lang'};
}
if (!$default_lang) {
$default_lang = "en";
}
if ($conf{'domain_rule'} =~ /^(.*?)=(.*?)$/) {
@domain_rules = (@domain_rules,$1);
$domain_rule{$1} = $2;
$REPORT .= "Domain rule configured: $1 = $2...\n";
}
my $mails_delivered;
my $mails_max = 100;
if ($data{'bot_community'} && $SITE && $DOMAIN && $conf{'site'} && $conf{'email'} && $conf{'bot_username'} && $conf{'bot_realname'}) {
$REPORT .= "Config is looking good: $conf{'site'}, $conf{'email'}, $conf{'bot_username'}, $conf{'bot_realname'}\n";
$REPORT .= "Connect to database '$data{'bot_community'}' ...\n";
my @txt = (
"This e\-mail has been automatically generated, so please don't reply - thank you!.",
"You've got private messages",
"Read your entire messages",
"Don't want to get informed about every new private message anymore?",
"Log into our website, select 'account' and disable the appropriate e\-mail settings.",
);
my @txt_de = (
"Diese Benachrichtigung wurde automatisch generiert, antworte also bitte nicht darauf - Danke!.",
"Du hast persönliche Nachrichten erhalten",
"Deine ganzen Nachrichten lesen",
"Du willst nicht mehr über jede einzelne persönliche Nachricht informiert werden?",
"Log dich in die Webseite ein, wähle 'Benutzerkonto' und nimm die entsprechenden E\-mail Einstellungen vor.",
);
my @txt_fr = (
"This e\-mail has been automatically generated, so please don't reply - thank you!.",
"Vous avez reçu des messages privés",
"Lire vos messages entiers",
"Don't want to get informed about new private messages anymore?",
"Log into our website, select 'account' and disable the appropriate e\-mail settings.",
);
my @txt_lu = (
"Diese Benachrichtigung wurde automatisch generiert, antworte also bitte nicht darauf - Danke!.",
"Du hues perséinlech Message kritt",
"Deng ganz Message liesen",
"Du willst nicht mehr über jede einzelne persönliche Nachricht informiert werden?",
"Log dich in die Webseite ein, wähle 'Benutzerkonto' und nimm die entsprechenden E\-mail Einstellungen vor.",
);
# mail queue
foreach my $dir (ONO::IO->ls("var/community/$data{'bot_community'}/mail_queue")) {
if ($dir !~ /\./ && $dir ne "config" && $mails_delivered < $mails_max && (
ONO::IO->devstation ||
$dir eq "1min" ||
($dir eq "5min" && $min%5 == 0) ||
($dir eq "10min" && ($min+1)%10 == 0) ||
($dir eq "15min" && ($min+2)%15 == 0) ||
($dir eq "30min" && ($min+3)%30 == 0) ||
($dir eq "1hour" && $min == 1) ||
($dir eq "2hour" && $min == 1 && $hour%2 == 0) ||
($dir eq "4hour" && $min == 1 && $hour%4 == 0)
)) {
$REPORT .= "Working in time-based directory '$dir':\n";
foreach my $queue (ONO::IO->ls("var/community/$data{'bot_community'}/mail_queue/$dir")) {
if ($queue !~ /^\./ && $queue =~ /[A-Za-z0-9]/ && $mails_delivered < $mails_max) {
$REPORT .= "+ Queue '$queue' found, loading the queue config...\n";
# default configs
if ($queue eq "messages") {
$conf{"messages_config_loaded"}++;
$conf{"messages_subject"} = $txt[1];
}
# load the queue config, make sure we'll only do this once
if (!$conf{"${queue}_config_loaded"}) {
$conf{"${queue}_config_loaded"}++;
my %qconf = &loadconf("","var/community/$data{'bot_community'}/mail_queue/config/$queue.conf");
foreach my $key (keys %qconf) {
$conf{"${queue}_$key"} = $qconf{$key};
}
}
if ($conf{"${queue}_subject"}) {
foreach my $sub (ONO::IO->ls("var/community/$data{'bot_community'}/mail_queue/$dir/$queue")) {
if ($sub !~ /^\./ && $sub =~ /[A-Za-z0-9]/ && $mails_delivered < $mails_max) {
$REPORT .= " - Sub-queue '$sub' found, processing...\n";
foreach my $file (ONO::IO->ls("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub")) {
if ($file !~ /^\./ && $file =~ /\.txt$/) {
my ($user,$mail,$lang,$flags,$domain);
if ($mails_delivered < $mails_max) {
# note that there is no cross-logic, so the DB may need to be accessed TWICE if
# one single user shall get mails that are encoded in a different way...
if ($file =~ /_AT_/ && $file =~ /_DOT_/ ) {
# case 1/2: the file encodes the EMAIL
$mail = ONO::Lib::Mail::ToolBox->file_to_email($file);
if ($cache{"mail_${file}_user"}) {
$user = $cache{"mail_${file}_user"};
$lang = $cache{"mail_${file}_lang"};
$flags = $cache{"mail_${file}_flags"};
$domain = $cache{"mail_${file}_domain"};
} else {
foreach my $line (ONO::DB->select($db,"$data{'bot_community'}_community_status","email = '$mail'")) {
my @col = ONO::DB->readcols($line);
$user = $col[0];
$cache{"mail_${file}_user"} = $user;
$lang = $col[5];
$lang =~ s~^:~~;
$lang =~ s~:(.*?)$~~;
$cache{"mail_${file}_lang"} = $lang;
$flags = $col[13];
$domain = $col[18];
$cache{"mail_${file}_flags"} = $flags;
$cache{"mail_${file}_domain"} = $domain;
}
}
} else {
# case 1/2: the file encodes the USERNAME
$user = lc $file;
$user =~ s~\.txt$~~;
$user =~ s~[^a-z0-9\-\_]~~g;
if ($cache{"user_${file}_mail"}) {
$mail = $cache{"user_${file}_mail"};
$lang = $cache{"user_${file}_lang"};
$flags = $cache{"user_${file}_flags"};
$domain = $cache{"user_${file}_domain"};
} else {
foreach my $line (ONO::DB->select($db,"$data{'bot_community'}_community_status","username = '$user'")) {
my @col = ONO::DB->readcols($line);
$mail = $col[17];
$cache{"user_${file}_mail"} = $mail;
$lang = $col[5];
$lang =~ s~^:~~;
$lang =~ s~:(.*?)$~~;
$cache{"user_${file}_lang"} = $lang;
$flags = $col[13];
$domain = $col[18];
$cache{"user_${file}_flags"} = $flags;
$cache{"user_${file}_domain"} = $domain;
}
}
}
}
if ($user && $mail && $domain) {
if (!$lang) {
$lang = $default_lang;
}
my @use_txt = @txt;
if ($lang eq "de") {
@use_txt = @txt_de;
}
if ($lang eq "fr") {
@use_txt = @txt_fr;
}
if ($lang eq "lu") {
@use_txt = @txt_lu;
}
$REPORT .= qq~ + Mail '$conf{"${queue}_subject"}' from '$SITE <noreply\@$DOMAIN>' to '$mail', using lang '$lang', flags '$flags', domain '$domain' ...\n~;
my $TEMPLATE;
my $USE_DOMAIN = $DOMAIN;
my $USE_SITE = $SITE;
if ($conf{'domain_rule'}) {
foreach my $rule (@domain_rules) {
if ($domain =~ /$rule/) {
$USE_DOMAIN = $conf{"domain_$domain_rule{$rule}"};
$USE_SITE = $conf{"site_$domain_rule{$rule}"};
$TEMPLATE = $conf{"mail_template_$domain_rule{$rule}"};
$REPORT .= qq~ + Domain rule applies: $rule = $domain_rule{$rule} ($USE_DOMAIN, $USE_SITE, $TEMPLATE) ...\n~;
}
}
}
my $MAIL;
foreach my $line (ONO::IO->list("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub/$file")) {
$MAIL .= $line;
}
if ($queue eq "messages") {
$MAIL .= qq~\n\n$use_txt[2]:\nhttps://$DOMAIN$conf{'software_base'}/account/?community_screen=messages\n\n\n$use_txt[3]\n$use_txt[4]~;
}
if ($TEMPLATE) {
ONO::ToolBox::SendMail->sendmail(
"$USE_DOMAIN <noreply\@$USE_DOMAIN>",
$mail,
qq~[$USE_SITE] $conf{"${queue}_subject"}~,
"$MAIL\n\n$use_txt[0]",
0,
"HT",
"",
"",
$TEMPLATE,
);
} else {
ONO::ToolBox::SendMail->sendmail(
"$USE_DOMAIN <noreply\@$USE_DOMAIN>",
$mail,
qq~[$USE_SITE] $conf{"${queue}_subject"}~,
"$MAIL\n\n$use_txt[0]",
0,
"H",
);
}
$mails_delivered++;
ONO::IO->rm("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub/$file");
} else {
$REPORT .= qq~ + User not identified ($user vs $mail), removing...\n~;
ONO::IO->rm("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub/$file");
}
}
}
$REPORT .= " - Cleaning up the queue...\n";
my $files;
foreach my $file (ONO::IO->ls("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub")) {
if ($file !~ /^\./ && $file =~ /\.txt$/) {
$files++;
}
}
if (!$files) {
$REPORT .= " + Queue subdir '$dir/$queue/$sub' has been removed...\n";
ONO::IO->rmdir("var/community/$data{'bot_community'}/mail_queue/$dir/$queue/$sub");
}
}
}
} else {
$REPORT .= " - no config found, skipping this queue...\n";
}
}
}
}
}
} else {
$REPORT .= "Config error [ABORT]\n";
}
ONO::IO->store("var/community/$data{'bot_community'}/mail_queue/report.txt",$REPORT);
}
if ($data{'type'} eq "bot_profiler") {
# this would better be part of the local Morzino code...
# foreach my $line (ONO::DB->select($db,"${community}_school_virclass:id,fullname,members")) {
# my @row = ONO::DB->readcols($line);
#
# # count members members
#
# my $members = ONO::DB->count($db,"${community}_school_virclass_relationships","virclass = '$row[0]' AND status = '1'");
#
# # update ranking (please note that this doesn't work well at the beginning of the year...)
#
# my $mon1 = $mon;
# my $month1 = ONO::IO->size(ONO::Ext::Morzino::ToolBox->virclass_dir($row[0])."activity/$year$mon1.txt");
#
# my $mon2 = $mon-1;
# if (length $mon2 < 2) {
# $mon2 = "0$mon2";
# }
# my $month2 = ONO::IO->size(ONO::Ext::Morzino::ToolBox->virclass_dir($row[0])."activity/$year$mon2.txt");
#
# my $mon3 = $mon-2;
# if (length $mon3 < 2) {
# $mon3 = "0$mon3";
# }
# my $month3 = ONO::IO->size(ONO::Ext::Morzino::ToolBox->virclass_dir($row[0])."activity/$year$mon3.txt");
#
# my $rank = int($members*100 + $month1 + $month2/2 + $month3/3);
#
# ################################################################
# # note that we could also count texts, images, blog entries aso here...
#
# # write back members and ranking...
#
# ONO::DB->command($db,"UPDATE ${community}_school_virclass SET members = '$members', rank = '$rank' WHERE id = '$row[0]';");
#
# $DATA .= &print (" - Class #$row[0] with $members members ('$row[1]'), rank: $rank",$switches);
#
# }
}
if ($data{'type'} eq "bot_signupreminder") {
#
# my %conf;
# my @lines = ONO::IO->list("cgi-bin/local/perl/$community/DEPRECATED/texts/config.txt");
# foreach my $line (@lines) {
# $line =~ s~(\n|\r|\t)~~g;
# my @lp = split(/ /,$line);
# if ($line =~ /\"(.*?)\"/) {
# $lp[1] = $1;
# }
# if ($lp[0] && $lp[1]) {
# $lp[1] =~ s~(\"|\')~~g;
# $conf{$lp[0]} = $lp[1];
# &print("Config : $lp[0] = $lp[1]",$switches);
# }
# }
#
# if ($conf{'gateway'} && $conf{'site'} && $conf{'domain'}) {
#
# my $db = ONO::DB->connect($community);
# my $log = "launching on $mday/$mon/$year \@ $hour:$min:$sec\n\n";
#
# my $list;
#
# foreach my $line (ONO::DB->select($db,"${community}_community_users","status = '0'")) {
# my @row = ONO::DB->readcols($line);
#
# if ($row[0] && $row[1] =~ /^(.*?)\@(.*?)\.(.*?)$/) {
# $list .= qq~$row[1], ~;
# }
# }
#
# $list =~ s~, $~~;
# open (MAIL, "|$sendmail -t");
# print MAIL "From: $conf{'site'} XXX\n";
# print MAIL "To: tracker\@$conf{'domain'}\n";
# print MAIL "Subject: \[$conf{'site'}\] Uncompleted e-mails\n";
# print MAIL "Content-Type: text/plain; charset=utf-8;\n\n";
# print MAIL qq~[$conf{'site'}] Signup Problems?\n
#
# ----------------------------------------------------------
# $conf{'site'} Signup | http://www.$conf{'domain'} | $mday.$mon.$year
# ----------------------------------------------------------\n
#
# Dear user,\n
#
# We noticed that you signed up on $conf{'site'} some time ago, but
# you didn't activate your account on the site:
# http://www.$conf{'domain'}\n
#
# It may be possible that you didn't get the account activation
# e-mail, such filtering problems have been detected with
# Hotmail and Yahoo mail accounts for example.\n
#
# So if you still wish to become a member (and we hope so!),
# please simply reply to this mail and we'll activate your
# account manually.\n
#
# Don't remember what $conf{'site'} was about?
# Check out the site:
# http://$conf{'domain'}\n
#
# If you do not wish to become a $conf{'site'} anymore and you'd like
# to get your e-mail address removed, simply reply to this mail
# by typing REMOVE as mail subject.\n
#
# Best regards
# The $conf{'site'} Team\n
#
# ----------------------------------------------------------\n
#
# http://www.$conf{'domain'}\n
#
# Login here and start adding friends right now:
# http://www.$conf{'domain'}/account\n
#
# Forgot your password? Go here:
# http://www.$conf{'domain'}/login/password\n
#
# ----------------------------------------------------------\n
# ~;
#
# print MAIL "$list\n";
# close (MAIL);
#
# } else {
# &print ("No gateway, site or domain in 'cgi-bin/local/perl/$community/DEPRECATED/texts/config.txt'",$switches);
# }
}
if ($data{'type'} eq "bot_media") {
$DATA .= ONO::Cron::CronSync::ToolBox->print("- Media Processor says 'HELLO' ...",$switches);
# images (not implemented yet)
if ($data{'bot_media_max_cpu_image'} && ONO::IO->sysload($data{'bot_media_max_cpu_image'}) && ",$data{'bot_media_exclude_hours'}," !~ ",$hour,") {
}
# audio + videos + pdf
# mail is not correctly implemented yet :/
my ($pdf_paused,$audio_paused,$video_paused);
if (ONO::IO->exists("var/tmp/cronsync/pdf_paused.txt")) {
if ($timestamp > ONO::IO->load("var/tmp/cronsync/pdf_paused.txt")) {
ONO::IO->rm("var/tmp/cronsync/pdf_paused.txt");
} else {
$pdf_paused++;
}
}
if (ONO::IO->exists("var/tmp/cronsync/audio_paused.txt")) {
if ($timestamp > ONO::IO->load("var/tmp/cronsync/audio_paused.txt")) {
ONO::IO->rm("var/tmp/cronsync/audio_paused.txt");
} else {
$audio_paused++;
}
}
if (ONO::IO->exists("var/tmp/cronsync/video_paused.txt")) {
if ($timestamp > ONO::IO->load("var/tmp/cronsync/video_paused.txt")) {
ONO::IO->rm("var/tmp/cronsync/video_paused.txt");
} else {
$video_paused++;
}
}
my (%used,$running,%counter);
$counter{'convert'} = 0;
$counter{'thumb'} = 0;
if (($data{'bot_media_max_cpu_pdf'} && ONO::IO->sysload($data{'bot_media_max_cpu_pdf'}) && ",$data{'bot_media_exclude_hours'}," !~ ",$hour," && !$pdf_paused) || $min%60 == 0) {
$DATA .= ONO::Cron::CronSync::ToolBox->print("- Media Processor PDF started",$switches);
my $REPORT2 = "$year/$mon/$mday \@ $hour:$min:$sec\n";
# standard PDF stuff
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/pdf2thumbqueue")) {
if ($ticket=~ /\.txt/ && !$pdf_paused) {
$counter{'convert'}++;
if (!$running && ONO::IO->sysload($data{'bot_media_max_cpu_pdf'})) {
my $FILE = ONO::IO->load("var/tmp/cronsync/pdf2thumbqueue/$ticket");
$REPORT2 .= "$ticket: $FILE\n";
if (!$used{$FILE}) {
$used{$FILE}++;
if ($FILE =~ m~\.pdf$~ && ONO::IO->exists($FILE)) {
my ($PR,$TN) = ONO::IO->getthumbs($FILE);
if (!ONO::IO->exists($PR) || !ONO::IO->exists($TN)) {
$running++;
$DATA .= ONO::Cron::CronSync::ToolBox->print("- MkThumb/PDF: $FILE",$switches);
my ($width,$height,$REPORT3) = ONO::ToolBox::Docs->mkthumb($FILE);
$REPORT2 .= "processing... [OK]\n$REPORT3\n";
ONO::IO->rm("var/tmp/cronsync/pdf2thumbqueue/$ticket");
} else {
$REPORT2 .= "thumbs exist... [DELETE + ABORT]\n";
ONO::IO->rm("var/tmp/cronsync/pdf2thumbqueue/$ticket");
}
} else {
$REPORT2 .= "bad file, or no such file [DELETE + ABORT]\n";
ONO::IO->rm("var/tmp/cronsync/pdf2thumbqueue/$ticket");
}
}
}
}
}
# bookmaker PDF jobs
if (!$running) {
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/bookmaker2pdfqueue")) {
if ($ticket=~ /\.txt/ && !$pdf_paused) {
$counter{'convert'}++;
if (!$running && ONO::IO->sysload($data{'bot_media_max_cpu_pdf'})) {
my $FILE = ONO::IO->load("var/tmp/cronsync/bookmaker2pdfqueue/$ticket");
$REPORT2 .= "$ticket: $FILE\n";
if (!$used{$FILE} && $FILE =~ /cronsync_request.txt$/) {
$used{$FILE}++;
my %book_vars;
foreach my $line (sort ONO::IO->list($FILE)) {
$line =~ s~(\n|\r|\t)~~g;
if ($line =~ /^(.*?)=(.*?)$/) {
$book_vars{$1} = $2;
$REPORT2 .= "book_vars $1 = $2\n";
}
}
$REPORT2 .= "bookmaker data loaded, now checking if $book_vars{'bookmaker_source'} exists...\n";
$DATA .= ONO::Cron::CronSync::ToolBox->print("- MkBook/PDF: $FILE",$switches);
if ($book_vars{'bookmaker_source'} =~ m~^media/users/~ && ONO::IO->exists($book_vars{'bookmaker_source'})) {
$book_vars{'app_option'} = "generated_recreate_now";
$REPORT2 .= "source exists, now processing...\n";
ONO::IO->rm("$book_vars{'bookmaker_source'}/export/book.pdf");
my ($FILES,$pages,$files_ref) = ONO::FW::Media::Books::BookMaker::App::Dir->dir("","",$book_vars{'bookmaker_dir'},\%book_vars,\%book_vars,\%book_vars);
ONO::FW::Media::Books::BookMaker::App::Generate->generate($book_vars{'app_input_paper_format_status'},$book_vars{'bookmaker_dir'},$files_ref,\%book_vars);
$REPORT2 .= "done!\n";
} else {
$REPORT2 .= "file not found, abort\n";
}
ONO::IO->rm("var/tmp/cronsync/bookmaker2pdfqueue/$ticket");
ONO::IO->rm($FILE);
ONO::IO->store("$book_vars{'bookmaker_source'}/reports/cronsync.txt",$REPORT2);
}
}
}
}
}
ONO::IO->store("var/tmp/cronsync/pdf_report.txt",$REPORT2);
}
if (($data{'bot_media_max_cpu_audio'} && ONO::IO->sysload($data{'bot_media_max_cpu_audio'}) && ",$data{'bot_media_exclude_hours'}," !~ ",$hour," && !$audio_paused) || $min%60 == 0) {
$DATA .= ONO::Cron::CronSync::ToolBox->print("- Media Processor AUDIO started",$switches);
my $REPORT2 = "$year/$mon/$mday \@ $hour:$min:$sec\n";
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/audio2mp3queue")) {
if ($ticket=~ /\.txt/ && !$audio_paused) {
$counter{'convert'}++;
if (!$running && ONO::IO->sysload($data{'bot_media_max_cpu_audio'})) {
my $FILE = ONO::IO->load("var/tmp/cronsync/audio2mp3queue/$ticket");
$REPORT2 .= "$ticket: $FILE\n";
if (!$used{$FILE}) {
$used{$FILE}++;
if ($FILE =~ m~\.(m4a|wma)$~ && ONO::IO->exists($FILE)) {
$running++;
$DATA .= ONO::Cron::CronSync::ToolBox->print("- AudioConvert: $FILE",$switches);
$REPORT2 .= ONO::Lib::Audio::ToolBox->convert("/$FILE",$timestamp,"_converted","X");
ONO::IO->rm("var/tmp/cronsync/audio2mp3queue/$ticket");
}
}
}
}
}
ONO::IO->store("var/tmp/cronsync/audio_report.txt",$REPORT2);
}
if (($data{'bot_media_max_cpu_video'} && ONO::IO->sysload($data{'bot_media_max_cpu_video'}) && ",$data{'bot_media_exclude_hours'}," !~ ",$hour," && !$video_paused) || $min%60 == 0) {
$DATA .= ONO::Cron::CronSync::ToolBox->print("- Media Processor VIDEO started",$switches);
my $REPORT2 = "$year/$mon/$mday \@ $hour:$min:$sec\n";
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/video2mp4queue")) {
if ($ticket=~ /\.txt/ && !$video_paused) {
$counter{'convert'}++;
if (!$running && ONO::IO->sysload($data{'bot_media_max_cpu_video'})) {
my $FILE = ONO::IO->load("var/tmp/cronsync/video2mp4queue/$ticket");
$REPORT2 .= "$ticket: $FILE\n";
if (!$used{$FILE}) {
$used{$FILE}++;
if ($FILE =~ m~\.(mpg|mpeg|m2ts|mov|mkv|f4v|avi|vob|wmv|flv|f4v|divx|webm|mp4c|ts)$~i && ONO::IO->exists($FILE)) {
$running++;
$DATA .= ONO::Cron::CronSync::ToolBox->print("- VideoConvert: $FILE",$switches);
$REPORT2 .= ONO::Lib::Video::ToolBox->convert("/$FILE",$timestamp,"_converted","X");
ONO::IO->rm("var/tmp/cronsync/video2mp4queue/$ticket");
}
if ($FILE =~ m~\.m4v$~ && ONO::IO->exists($FILE)) {
$running++;
my $NEW = $FILE;
$NEW =~ s~\.m4v$~\.mp4~i;
ONO::IO->mv($FILE,$NEW);
ONO::IO->rm("var/tmp/cronsync/video2mp4queue/$ticket");
}
}
}
}
}
if (!$running) {
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/video2thumbqueue")) {
if ($ticket=~ /\.txt/ && !$video_paused) {
$counter{'thumb'}++;
if (!$running && ONO::IO->sysload($data{'bot_media_max_cpu_video'})) {
my $FILE = ONO::IO->load("var/tmp/cronsync/video2thumbqueue/$ticket");
$REPORT2 .= "$ticket: $FILE\n";
if (!$used{$FILE}) {
$used{$FILE}++;
if ($FILE =~ m~\.(mp4|mpg|mpeg|m2ts|mov|mkv|f4v|avi|vob|wmv|flv|f4v|divx|webm|mp4c|ts)$~i && ONO::IO->exists($FILE)) {
my ($PR,$TN) = ONO::IO->getthumbs($FILE);
if (!ONO::IO->exists($PR) || !ONO::IO->exists($TN)) {
$REPORT2 .= "processing... [OK]\n";
$running++;
$DATA .= ONO::Cron::CronSync::ToolBox->print("- VideoConvert: $FILE",$switches);
ONO::Lib::Video::ToolBox->mkthumb("/$FILE",$timestamp);
ONO::IO->rm("var/tmp/cronsync/video2thumbqueue/$ticket");
} else {
$REPORT2 .= "thumbs exist... [DELETE + ABORT]\n";
ONO::IO->rm("var/tmp/cronsync/video2thumbqueue/$ticket");
}
} else {
$REPORT2 .= "bad file, or no such file... [DELETE + ABORT]\n";
ONO::IO->rm("var/tmp/cronsync/video2thumbqueue/$ticket");
}
}
}
}
}
}
ONO::IO->store("var/tmp/cronsync/video_report.txt",$REPORT2);
# ONO::IO->store("var/tmp/cronsync/video2thumbqueue_report.txt",$REPORT2);
}
if ($min%15 == 0) {
my ($SITE,$DOMAIN) = ONO::Cron::CronSync::ToolBox->get_site();
if ($SITE && $DOMAIN) {
my $total_tickets = 0;
my ($TX,$TXINFO);
foreach my $queue (sort ONO::IO->ls("var/tmp/cronsync")) {
if ($queue =~ /[a-z]/ && $queue !~ /\./) {
my $queue_tickets = 0;
foreach my $ticket (ONO::IO->ls("var/tmp/cronsync/$queue")) {
if ($ticket=~ /\.txt/) {
$total_tickets++;
$queue_tickets++;
}
}
if ($queue_tickets) {
$TX .= "$queue_tickets, ";
$TXINFO .= "$queue_tickets found in ticket queue '$queue'.\n\n";
}
}
}
if ($total_tickets) {
$TX =~ s~, $~~;
ONO::ToolBox::SendMail->sendmail(
"$DOMAIN <noreply\@$DOMAIN>",
"mail:tracker",
"[$SITE] Tickets in media queue: $total_tickets ($TX)",
$TXINFO,
);
}
}
}
# my ($load1,$load2,$load3) = ONO::ToolBox::LoadBalancer->get_load;
#
# &print(" Current CPU load is $load1,$load2,$load3",$switches);
# &print(" Note: -f will overrun CPU load limits",$switches);
#
# ################################################################
# # CONFIG
# ################################################################
#
# my %conf;
# my @lines = ONO::IO->list("var/community/$community/bot/config.txt");
# foreach my $line (@lines) {
# $line =~ s~(\n|\r|\t)~~g;
# my @lp = split(/ /,$line);
# if ($line =~ /\"(.*?)\"/) {
# $lp[1] = $1;
# }
# if ($lp[0] && $lp[1]) {
# $lp[1] =~ s~(\"|\')~~g;
# $conf{$lp[0]} = $lp[1];
# $DATA .= &print("Config : $lp[0] = $lp[1]",$switches);
# }
# }
#
# my $site;
# if ($conf{'site'}) {
# $site = "[$conf{'site'}] ";
# }
#
# if (-e "$vpath/etc/sql/$community.conf" && (($load1 < 110 && $load2 < 120 && $load3 < 110) || $switches =~ /f/)) {
#
# $DATA .= &print(" Trying to connect to the database...",$switches);
# my $db = ONO::DB->connect($community);
#
# if ($db) {
# $DATA .= &print(" Database OK...",$switches);
# $DATA .= &print(" Launching ONO Image ToolKit...",$switches);
#
# ######################################################################
# # device manager pipelines
# ######################################################################
#
# $DATA .= &print(" + Device Manager Pipelines",$switches);
#
# my ($counter,%used);
# my $user_file = ONO::IO->load("var/community/$community/tmp/devices/image_upload.txt");
# my @users = split(/:/,$user_file);
# foreach my $user (@users) {
# if ($user =~ /[a-z0-9]/ && !$used{$user}) {
#
# $used{$user}++;
# $DATA .= &print(" - $user ",$switches);
#
# my $dir = ONO::FW::User::Init->getuserdir($user,$community);
# $dir =~ s~^var/community/$community/accounts/data/~media/users/~;
#
# my @files = ONO::IO->dir("$dir/devices");
# foreach my $file (@files) {
#
# my ($pr,$tn) = ONO::IO->getthumbs("$dir/devices/$file");
#
# if ($file !~ /^\./ && $file =~ /\.jpg$/ && !ONO::IO->exists($pr) && !ONO::IO->exists($tn) && $counter < 10) {
#
# $counter++;
#
# my (
# $status,
# $width,
# $height,
# ) = ONO::Lib::Image::Magick->resize("/$dir/devices/$file","","max:920","max:920");
#
# ONO::ToolBox::Docs->mkthumb("$dir/devices/$file");
#
# }
# }
#
# }
# }
#
# # write back the tmp file data if there were 10 or more images,
# # in this case we'll have to redo everything next time...
#
# if ($counter > 9) {
# ONO::IO->append("var/community/$community/tmp/devices/image_upload.txt",$user_file );
# ONO::IO->chmod("var/community/$community/tmp/devices/image_upload.txt","777" );
# }
#
# ######################################################################
# # profile pics
# ######################################################################
#
# my ($load1,$load2,$load3) = ONO::ToolBox::LoadBalancer->get_load;
# if ($load1 > 110 && $load2 > 120 && $load3 > 110 && $switches !~ /f/) {
# $DATA .= &print(" + CPU load too high right now [ABORT]",$switches);
# } else {
#
# $DATA .= &print(" + Profile Pics",$switches);
#
# foreach my $line (ONO::DB->select($db,"${community}_community_profiles","image LIKE '%x%'","ORDER BY RAND()","LIMIT 10")) {
# my @col = ONO::DB->readcols($line);
#
# my $dir = ONO::FW::User::Init->getuserdir($col[0],$community);
# $dir =~ s~^var/community/$community/accounts/data/~images/users/~;
#
# my ($pr,$tn) = ONO::IO->getthumbs("$dir.jpg");
#
# my (
# $status,
# $width,
# $height,
# ) = ONO::Lib::Image::Magick->resize("/$dir.jpg","/$tn","max:120","max:120");
#
# $DATA .= &print(" - $col[0] [ $tn ]",$switches);
#
# }
# }
#
# ######################################################################
# # docs
# ######################################################################
#
# my ($load1,$load2,$load3) = ONO::ToolBox::LoadBalancer->get_load;
# if ($load1 > 1.20 && $load2 > 130 && $load3 > 120 && $switches !~ /f/) {
# $DATA .= &print(" + CPU load too high right now [ABORT]",$switches);
# } else {
#
# $DATA .= &print(" + Docs",$switches);
#
# ###################################################################
# # make .pr and .tn
# ###################################################################
#
# foreach my $line (ONO::DB->select($db,"${community}_docs_files","width < 801 AND height < 801","ORDER BY RAND()","LIMIT 10")) {
# my @col = ONO::DB->readcols($line);
#
# my ($load1,$load2,$load3) = ONO::ToolBox::LoadBalancer->get_load;
# if ($load1 > 140 && $load2 > 150 && $load3 > 140 && $switches !~ /f/) {
#
# $DATA .= &print(" - $col[2] - CPU load too high [ABORT]",$switches);
#
# } else {
#
# $DATA .= &print(" - $col[2]",$switches);
# my ($pr,$tn) = ONO::IO->getthumbs("$col[2].jpg");
#
# if (!ONO::IO->exists($pr) || !ONO::IO->exists($pr)) {
#
# $DATA .= &print(" + [creating / updating thumbs...]",$switches);
#
# ONO::ToolBox::Docs->mkthumb($col[2],$col[1]);
#
# } else {
#
# $DATA .= &print(" + [thumbs exist, overrun]",$switches);
#
# }
#
# }
#
# }
#
# foreach my $line (ONO::DB->select($db,"${community}_docs_files","width > 920 OR height > 920","RAND()","LIMIT 5")) {
# my @col = ONO::DB->readcols($line);
#
# if ($col[18] !~ /H/) {
#
# my ($load1,$load2,$load3) = ONO::ToolBox::LoadBalancer->get_load;
# if ($load1 > 300 && $load2 > 250 && $load3 > 200 && $switches !~ /f/) {
#
# $DATA .= &print(" - $col[2] - CPU load too high [ABORT]",$switches);
#
# } else {
#
# # don't resize images in the /images directory (admin)
#
# if ($col[2] !~ /^images\//) {
#
# my (
# $status,
# $width,
# $height,
# ) = ONO::Lib::Image::Magick->resize("/$col[2]","","max:920","max:920");
#
# ONO::ToolBox::Docs->mkthumb($col[2],$col[1]);
#
# my $size = ONO::IO->size($col[2]);
#
# ONO::DB->command($db,"UPDATE ${community}_docs_files SET
# width = '$width',
# height = '$height',
# size = '$size'
# WHERE id_10 = '$col[1]';");
#
# $DATA .= &print(" - $col[2] ($col[25]x$col[26] -> ${width}x${height})",$switches);
#
# }
# }
# }
# }
# }
# } else {
# $DATA .= &print(" No database connection using '$vpath/etc/sql/$ARGV[0].conf'",$switches);
# }
#
# } else {
# $DATA .= &print(" CPU load too high, or no such database config: '$vpath/etc/sql/$ARGV[0].conf'",$switches);
# }
#
# if ($switches =~ /m/) {
# ONO::ToolBox::SendMail->sendmail(
# "mail:noreply",
# "$conf{'email'}",
# "${site}Image Robot",
# $DATA,
# );
# }
}
return ($DATA,$MAIL);
}
sub loadconf {
my %conf;
foreach my $line (ONO::IO->list($_[1])) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/ /,$line);
if ($line =~ /\"(.*?)\"/) {
$lp[1] = $1;
}
if ($lp[0] && $lp[1]) {
$lp[1] =~ s~(\"|\')~~g;
$conf{$lp[0]} = $lp[1];
$conf{lc $lp[0]} = $lp[1];
}
}
return %conf;
}
###############################################################################
# end of script
###############################################################################
1;
__END__