soselo/cron.php

222 lines
5.7 KiB
PHP

<?php chdir(__DIR__) ?>
<?php require 'base.php' ?>
<?php
if (file_exists('.cron.lock'))
die('cron.php is locked by ".cron.lock"');
touch('.cron.lock');
function logi($thing) { echo date('Y/m/d H:i:s').' INFO | '.strval($thing)."\n"; }
function loge($thing) { echo date('Y/m/d H:i:s').' ERROR | '.strval($thing)."\n"; }
function end_cronjobs() {
unlink('.cron.lock');
die;
}
////////////////
// INITIAL SETUP
//
$GLOBALS['_crondir'] = $GLOBALS['appconf']['data_dir'].'/cron';
if (!file_exists($GLOBALS['_crondir'])) {
mkdir($GLOBALS['_crondir']);
end_cronjobs();
}
$time_start = time();
//
////////////////
////////////////////////////////
// CRONJOBS for database caching
//
function run__cronjobs_db() {
$dir = $GLOBALS['_crondir'].'/db';
if (!file_exists($dir)) {
mkdir($dir);
return false;
}
$jobs = [];
foreach (scandir($dir) as $jf) {
if (in_array($jf,['.','..']))
continue;
$ps = explode(',',$jf);
$jobs []= (object)[
'id' => $ps[2],
'file' => $dir.'/'.$jf,
'software' => $ps[0],
'instance' => $ps[1],
'time' => intval($ps[3]),
];
}
foreach ($jobs as $job) {
$ms = time() - filemtime($job->file);
$sql = file_get_contents($job->file);
if ($ms < $job->time) continue;
logi("Processing job: {$job->id}, software={$job->software}, instance={$job->instance}");
$ok = false;
switch ($job->software) {
case 'mastodon':
$pg = new PgDatabase($job->software, $job->instance);
if ($pg->is_ok()) {
$result = $pg->fetch_all($sql);
content_cache__put($job->software.$job->instance.$sql, 'always,'.$job->time, $result);
$pg->close();
$ok = true;
}
break;
}
if ($ok) {
logi("Job done: {$job->id}");
touch($job->file);
}
}
}
run__cronjobs_db();
//
////////////////////////////////
///////////////////////////////
// CRONJOBS for caching cleanup
//
function run__cronjobs_cache_cleanup() {
$cache_dir = $GLOBALS['appconf']['data_dir'].'/cache';
if (!file_exists($cache_dir))
return;
foreach (scandir($cache_dir) as $fl) {
if (in_array($fl, ['.','..']))
continue;
$ps = explode(',',$fl);
if ($ps[1] !== 'ondemand')
continue;
$time = intval($ps[2]);
$mtime = filemtime($cache_dir.'/'.$fl);
if (time() - $mtime >= $time) {
logi('CACHE-CLEANUP remove old file: '.$fl);
unlink($cache_dir.'/'.$fl);
}
}
}
run__cronjobs_cache_cleanup();
//
///////////////////////////////
//////////////////////////////////////////
// CRONJOBS for creating jobs from filters
//
function run__cronjobs_filter_job($software, $instance, $filter, $action) {
$_GET = [
'filter_id' => $filter['id'],
'instance' => $instance
];
logi('Processing filter: '.serialize($_GET));
$users = mod_php('api/v1/database/'.$software.'/accounts/search');
if (gettype($users) !== 'array' || isset($users['error'])) {
loge('Unexpected value for users: '.strval($users));
return false;
}
if (!isset($users['data'])) {
loge('Unexpected value for users: '.strval($users));
return false;
}
foreach ($users['data'] as $user) {
$jobname = $action['action']['name'].'_'.$user['id'];
$jobmod = 'api/v1/http/'.$software.'/accounts/'.$action['action']['name'];
$report = '[automatic_report] User has been reported because it matches filter "'.$filter['preset_name'].'"';
$args = base64_encode(json_encode([
'_get' => [
'id' => $user['id'],
'instance' => $instance,
],
'_post' => ['report' => $report ],
]));
$_POST = [
'name' => $jobname,
'module' => $jobmod,
'args' => $args,
];
$result = mod_php('api/v1/cron/job/put');
if (isset($result['ok']))
logi($result['ok']);
else if (isset($result['error']))
loge($result['error']);
}
touch($GLOBALS['appconf']['data_dir'].'/filter_actions/users,'.$instance.','.$action['id']);
return true;
}
function run__cronjobs_filter_jobs() {
$_GET = ['type' => 'users'];
$filters = mod_php('api/v1/config/filters/get');
$config = mod_php('api/v1/config/get');
$filter_get = function($filters, $id) {
foreach ($filters as $f)
if ($f['id'] === $id)
return $f;
return null;
};
foreach ($GLOBALS['supported_ap_software'] as $software) {
foreach ($config['hosts'][$software] as $hostcfg) {
$_GET['instance'] = $hostcfg['instance'];
$actions = mod_php('api/v1/config/filters/actions/get');
if ($actions === null) continue;
foreach ($actions as $action) {
$filter = $filter_get($filters, $action['id']);
if ($filter === null) continue;
$ts_diff = time() - $action['filemtime'];
if ($ts_diff >= $action['action']['interval'])
run__cronjobs_filter_job($software,
$hostcfg['instance'], $filter, $action);
}
}
}
}
run__cronjobs_filter_jobs();
//
//////////////////////////////////////////
///////////////////////////////////////
// CRONJOBS for running the actual jobs
//
function run_cronjobs() {
$max = 1000;
if (isset($GLOBALS['appconf']['cron__max_jobs']))
$max = intval($GLOBALS['appconf']['cron__max_jobs']);
$_GET = ['max' => $max];
$jobs = mod_php('api/v1/cron/jobs');
foreach ($jobs as $job) {
$_GET = ['id' => $job];
$job_data = mod_php('api/v1/cron/job/get');
if (isset($job_data['args']['_get']))
$_GET = $job_data['args']['_get'];
if (isset($job_data['args']['_post']))
$_POST = $job_data['args']['_post'];
logi('Running job with data: '.serialize($job_data));
$r = mod_php($job_data['module']);
if ($r === 'does_not_exist') {
loge('Could not find module (mod.php file) for: '.$job_data['module']);
continue;
}
$_GET = ['id' => $job];
$result = mod_php('api/v1/cron/job/del');
if (isset($result['ok']))
logi($result['ok']);
else if (isset($result['error']))
loge($result['error']);
}
}
run_cronjobs();
//
///////////////////////////////////////
$ms_total = time() - $time_start;
logi("Cron has finished in {$ms_total} seconds");
end_cronjobs();