package ONO::Cron::CronSync::Bot;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2022-2026 Jos Kirps and The Joopita Project [ASBL]
# Copyright (C) 2011-2022 Jos Kirps and Joopita Research ASBL
# Copyright (C) 2006-2011 Jos Kirps and The Joopita Project
# Copyright (C) 2001-2006 Jos Kirps and The WobbleWolf Project
#
# This file, as well as many 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_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/?user_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_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,
);
}
}
}
}
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__