This commit is contained in:
Zi Xing 2021-12-18 20:23:02 -05:00
commit 27c51bdd23
8 changed files with 939 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build/

1
.ppm_package Normal file
View File

@ -0,0 +1 @@
botsrc

41
Makefile Normal file
View File

@ -0,0 +1,41 @@
clean:
# Removes the build directory
rm -rf build
update:
# Updates the package.json file
ppm --generate-package="botsrc"
build:
# Compiles the package
mkdir build
ppm --compile="botsrc" --directory="build"
install:
# Installs the compiled package to the system
ppm --fix-conflict --no-prompt --install="build/net.intellivoid.spam_protection_bot.ppm" --branch="production"
install_fast:
# Installs the compiled package to the system
ppm --fix-conflict --no-prompt --skip-dependencies --install="build/net.intellivoid.spam_protection_bot.ppm" --branch="production"
run:
# Runs the bot
ppm --main="net.intellivoid.spam_protection_bot" --version="latest"
stop:
# Stops the main execution point
pkill -f 'main=net.intellivoid.spam_protection_bot'
stop_workers:
# Stops the sub-workers created by BackgroundWorker
pkill -f 'worker-name=PublicServerchanBot'
debug:
# Starts the bot, kills all the workers and focuses on one worker in STDOUT
# Run with -i to ignore possible errors.
make stop
screen -dm bash -c 'ppm --main="net.intellivoid.spam_protection_bot" --version="latest"'
sleep 3
make stop_workers
php botsrc/worker.php

7
botsrc/.htaccess Normal file
View File

@ -0,0 +1,7 @@
Options -Indexes
Order deny,allow
Deny from all
<Files "index.php">
Allow from all
</Files>

227
botsrc/SynicalBot.php Normal file
View File

@ -0,0 +1,227 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
use acm2\acm2;
use acm2\Objects\Schema;
use BackgroundWorker\BackgroundWorker;
use CoffeeHouse\CoffeeHouse;
use DeepAnalytics\DeepAnalytics;
use SpamProtection\SpamProtection;
use TelegramClientManager\TelegramClientManager;
use VerboseAdventure\VerboseAdventure;
/**
* Class SpamProtectionBot
*/
class SynicalBot
{
/**
* The last Unix Timestamp when the worker was invoked
*
* @var int
*/
public static $LastWorkerActivity;
/**
* Indicates if this worker is sleeping
*
* @var bool
*/
public static $IsSleeping;
/**
* @var TelegramClientManager
*/
public static $TelegramClientManager;
/**
* @var BackgroundWorker
*/
public static $BackgroundWorker;
/**
* @var VerboseAdventure
*/
public static $LogHandler;
/**
* Auto configures ACM
*
* @return acm2
*/
public static function autoConfig(): acm2
{
$acm = new acm2('SynicalBot');
$TelegramSchema = new Schema();
$TelegramSchema->setName('TelegramService');
$TelegramSchema->setDefinition('BotName', '<BOT NAME HERE>');
$TelegramSchema->setDefinition('BotToken', '<BOT TOKEN>');
$TelegramSchema->setDefinition('BotEnabled', true);
$TelegramSchema->setDefinition('UseTestServers', false);
$TelegramSchema->setDefinition('EnableCustomServer', true);
$TelegramSchema->setDefinition('CustomEndpoint', 'http://127.0.0.1:8081');
$TelegramSchema->setDefinition('CustomDownloadEndpoint', '/file/bot{API_KEY}');
$TelegramSchema->setDefinition('MainOperators', []);
$TelegramSchema->setDefinition('LoggingChannel', 'SpamProtectionLogs');
$TelegramSchema->setDefinition('VerboseLogging', false);
$acm->defineSchema($TelegramSchema);
$BackgroundWorkerSchema = new Schema();
$BackgroundWorkerSchema->setName('BackgroundWorker');
$BackgroundWorkerSchema->setDefinition('Host', '127.0.0.1');
$BackgroundWorkerSchema->setDefinition('Port', 4730);
$BackgroundWorkerSchema->setDefinition('MaxWorkers', 5);
$acm->defineSchema($BackgroundWorkerSchema);
$RedisSchema = new Schema();
$RedisSchema->setName('Redis');
$RedisSchema->setDefinition('Host', '127.0.0.1');
$RedisSchema->setDefinition('Port', 6379);
$RedisSchema->setDefinition('Username', '');
$RedisSchema->setDefinition('Password', '');
$RedisSchema->setDefinition('Database', 0);
$acm->defineSchema($RedisSchema);
$acm->updateConfiguration();
return $acm;
}
/**
* Returns the Telegram Service configuration
*
* @return mixed
* @throws Exception
*/
public static function getTelegramConfiguration()
{
return self::autoConfig()->getConfiguration('TelegramService');
}
/**
* Returns the database configuration
*
* @return mixed
* @throws Exception
*/
public static function getDatabaseConfiguration()
{
return self::autoConfig()->getConfiguration('Database');
}
/**
* Returns the redis configuration
*
* @return mixed
* @throws Exception
* @noinspection PhpUnused
*/
public static function getRedisConfiguration()
{
return self::autoConfig()->getConfiguration('Redis');
}
/**
* Returns the background worker configuration
*
* @return mixed
* @throws Exception
*/
public static function getBackgroundWorkerConfiguration()
{
return self::autoConfig()->getConfiguration('BackgroundWorker');
}
/**
* @return TelegramClientManager
*/
public static function getTelegramClientManager(): TelegramClientManager
{
return self::$TelegramClientManager;
}
/**
* @return BackgroundWorker
*/
public static function getBackgroundWorker(): BackgroundWorker
{
return self::$BackgroundWorker;
}
/**
* @return VerboseAdventure
*/
public static function getLogHandler(): VerboseAdventure
{
return self::$LogHandler;
}
/**
* @param VerboseAdventure $LogHandler
*/
public static function setLogHandler(VerboseAdventure $LogHandler): void
{
self::$LogHandler = $LogHandler;
}
/**
* @return int
*/
public static function getLastWorkerActivity(): int
{
return self::$LastWorkerActivity;
}
/**
* @param int $LastWorkerActivity
* @noinspection PhpUnused
*/
public static function setLastWorkerActivity(int $LastWorkerActivity): void
{
self::$LastWorkerActivity = $LastWorkerActivity;
}
/**
* @return bool
*/
public static function isSleeping(): bool
{
return self::$IsSleeping;
}
/**
* @param bool $IsSleeping
*/
public static function setIsSleeping(bool $IsSleeping): void
{
self::$IsSleeping = $IsSleeping;
}
/**
* Determines if this current worker should save resources by going to sleep or wake up depending on the
* last activity cycle
* @noinspection PhpUnused
*/
public static function processSleepCycle()
{
if(time() - self::getLastWorkerActivity() > 60)
{
if(self::isSleeping() == false)
{
self::getTelegramClientManager()->disconnectDatabase();
self::setIsSleeping(true);
}
}
else
{
if(self::isSleeping() == true)
{
self::getTelegramClientManager()->connectDatabase();
self::setIsSleeping(false);
}
}
}
}

177
botsrc/main Normal file
View File

@ -0,0 +1,177 @@
<?php
/** @noinspection PhpDefineCanBeReplacedWithConstInspection */
/** @noinspection DuplicatedCode */
/**
* main is the main execution point for the bot to start polling, this method uses BackgroundWorker to
* instantly process a batch of updates in the background without waiting for the updates to be completed.
*
* In exchange for this performance upgrade, each worker will use up database connections, make sure
* the database can handle these connections without maxing out
*/
use BackgroundWorker\BackgroundWorker;
use Longman\TelegramBot\Exception\TelegramException;
use Longman\TelegramBot\Request;
use ppm\ppm;
use ProcLib\Abstracts\Types\StdType;
use ProcLib\Process;
use ProcLib\Utilities\PhpExecutableFinder;
use VerboseAdventure\Abstracts\EventType;
use VerboseAdventure\Classes\ErrorHandler;
use VerboseAdventure\VerboseAdventure;
// Import all required auto loaders
/** @noinspection PhpIncludeInspection */
require('ppm');
/** @noinspection PhpUnhandledExceptionInspection */
ppm::import('net.intellivoid.spam_protection_bot');
VerboseAdventure::setStdout(true); // Enable stdout
ErrorHandler::registerHandlers(); // Register error handlers
// Load all configurations
/** @noinspection PhpUnhandledExceptionInspection */
$TelegramServiceConfiguration = SynicalBot::getTelegramConfiguration();
/** @noinspection PhpUnhandledExceptionInspection */
$DatabaseConfiguration = SynicalBot::getDatabaseConfiguration();
/** @noinspection PhpUnhandledExceptionInspection */
$BackgroundWorkerConfiguration = SynicalBot::getBackgroundWorkerConfiguration();
// Create the Telegram Bot instance (NO SQL)
define('TELEGRAM_BOT_NAME', $TelegramServiceConfiguration['BotName']);
SynicalBot::setLogHandler(new VerboseAdventure(TELEGRAM_BOT_NAME));
SynicalBot::getLogHandler()->log(EventType::INFO, 'Starting Service', 'Main');
try
{
if($TelegramServiceConfiguration['EnableCustomServer'])
{
Request::setCustomBotApiUri(
$TelegramServiceConfiguration['CustomEndpoint'],
$TelegramServiceConfiguration['CustomDownloadEndpoint']
);
define('TELEGRAM_ENDPOINT', $TelegramServiceConfiguration['CustomEndpoint']);
define('TELEGRAM_DOWNLOAD_ENDPOINT',
str_ireplace('{API_KEY}', $TelegramServiceConfiguration['BotToken'], $TelegramServiceConfiguration['CustomDownloadEndpoint']));
}
else
{
define('TELEGRAM_ENDPOINT', 'https://api.telegram.org');
define('TELEGRAM_DOWNLOAD_ENDPOINT', '/file/bot' . $TelegramServiceConfiguration['BotToken']);
}
$telegram = new Longman\TelegramBot\Telegram(
$TelegramServiceConfiguration['BotToken'],
$TelegramServiceConfiguration['BotName'],
$TelegramServiceConfiguration['UseTestServers']
);
$telegram->setVerboseLogging($TelegramServiceConfiguration['VerboseLogging']);
}
catch (Longman\TelegramBot\Exception\TelegramException $e)
{
SynicalBot::getLogHandler()->logException($e, 'Main');
exit(255);
}
$telegram->useGetUpdatesWithoutDatabase();
// Start the workers using the supervisor
SynicalBot::getLogHandler()->log(EventType::INFO, 'Starting Supervisor', 'Main');
try
{
SynicalBot::$BackgroundWorker = new BackgroundWorker();
SynicalBot::$BackgroundWorker->getSupervisor()->setDisplayOutput(TELEGRAM_BOT_NAME, true);
SynicalBot::getBackgroundWorker()->getClient()->addServer($BackgroundWorkerConfiguration['Host'], (int)$BackgroundWorkerConfiguration['Port']);
SynicalBot::getBackgroundWorker()->getSupervisor()->startWorkers(
getcwd() . DIRECTORY_SEPARATOR . 'worker', TELEGRAM_BOT_NAME,
(int)$BackgroundWorkerConfiguration['MaxWorkers']
);
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Main');
exit(255);
}
// Start the verdict thread
$phpExecutableFinder = new PhpExecutableFinder();
$phpBinLocation = $phpExecutableFinder->find();
$VerdictThread = new Process([$phpBinLocation, getcwd() . DIRECTORY_SEPARATOR . 'verdict_worker']);
$VerdictCallbackThread = function ($type, $buffer)
{
$buffer_split = implode("\n", explode("\r\n", $buffer));
$buffer_split = explode("\n", $buffer_split);
foreach ($buffer_split as $item) {
if (strlen($item) == 0)
{
continue;
}
if (stripos($item, 'flush(gearman_could_not_connect)'))
{
continue;
}
switch (strtolower($type)) {
case "out":
case StdType::STDOUT:
SynicalBot::getLogHandler()->log(EventType::INFO, $item, 'Verdict Thread');
break;
case "err":
case StdType::STDERR:
SynicalBot::getLogHandler()->log(EventType::ERROR, $item, 'Verdict Thread');
break;
}
}
};
$VerdictThread->start($VerdictCallbackThread);
$next_event_update = time() + 60;
$total_update_count = 0;
// Start listening to updates
while(true)
{
/** @noinspection PhpUnhandledExceptionInspection */
SynicalBot::$BackgroundWorker->getSupervisor()->monitor(TELEGRAM_BOT_NAME);
if($VerdictThread->isRunning() == false)
{
$VerdictThread->restart($VerdictCallbackThread);
}
try
{
$server_response = $telegram->handleBackgroundUpdates(SynicalBot::getBackgroundWorker());
if ($server_response->isOk())
{
$update_count = count($server_response->getResult());
if($update_count > 0)
{
$total_update_count += $update_count;
if(time() >= $next_event_update)
{
SynicalBot::getLogHandler()->log(EventType::INFO, 'Processed ' . $total_update_count . ' update(s)', 'Main');
$total_update_count = 0;
$next_event_update = time() + 60;
}
}
}
else
{
SynicalBot::getLogHandler()->log(EventType::ERROR, 'Failed to fetch updates: ' . $server_response->printError(true), 'Main');
}
}
catch (TelegramException $e)
{
SynicalBot::getLogHandler()->logException($e, 'Main');
}
}

233
botsrc/package.json Normal file
View File

@ -0,0 +1,233 @@
{
"package": {
"package_name": "net.intellivoid.synical_bot",
"name": "Telegram SynicalBot",
"version": "3.0.0.0",
"author": "Zi Xing Narrakas",
"organization": "Intellivoid",
"description": "A next-generation group management bot",
"url": "https://github.com/intellivoid/SynicalBot",
"dependencies": [
{
"package": "net.intellivoid.acm2",
"version": "latest",
"source": "default@github/intellivoid/acm2",
"required": true
},
{
"package": "net.intellivoid.background_worker",
"version": "latest",
"source": "default@github/intellivoid/BackgroundWorker",
"required": true
},
{
"package": "net.intellivoid.coffeehouse",
"version": "latest",
"source": "default@github/intellivoid/coffeehouse",
"required": true
},
{
"package": "net.intellivoid.deepanalytics",
"version": "latest",
"source": "default@github/intellivoid/DeepAnalytics",
"required": true
},
{
"package": "net.intellivoid.spam_protection",
"version": "latest",
"source": "default@github/intellivoid/SpamProtection",
"required": true
},
{
"package": "net.intellivoid.telegram_client_manager",
"version": "latest",
"source": "default@github/intellivoid/IVA-Telegram",
"required": true
},
{
"package": "net.intellivoid.pop",
"version": "latest",
"source": "default@github/intellivoid/pop",
"required": true
},
{
"package": "net.intellivoid.msqg",
"version": "latest",
"source": "default@github/intellivoid/msqg",
"required": true
},
{
"package": "net.intellivoid.ziproto",
"version": "latest",
"source": "default@github/intellivoid/ziproto",
"required": true
},
{
"package": "net.intellivoid.verbose_adventure",
"version": "latest",
"source": "default@github/intellivoid/VerboseAdventure",
"required": true
},
{
"package": "net.intellivoid.tdlib",
"version": "latest",
"source": "default@github/intellivoid/tdlib",
"required": true
},
{
"package": "net.intellivoid.tmpfile",
"version": "latest",
"source": "default@github/intellivoid/TmpFile",
"required": true
},
{
"package": "net.intellivoid.proclib",
"version": "latest",
"source": "default@github/intellivoid/ProcLib",
"required": true
}
],
"configuration": {
"autoload_method": "generated_spl",
"main": {
"execution_point": "main",
"create_symlink": false,
"name": null
},
"post_installation": [],
"pre_installation": []
}
},
"components": [
{
"required": true,
"file": "commands/AgdemoteCommand.php"
},
{
"required": true,
"file": "commands/AgpromoteCommand.php"
},
{
"required": true,
"file": "commands/AppealCommand.php"
},
{
"required": true,
"file": "commands/BakaMitaiCommand.php"
},
{
"required": true,
"file": "commands/BlacklistCommand.php"
},
{
"required": true,
"file": "commands/BlCommand.php"
},
{
"required": true,
"file": "commands/CallbackqueryCommand.php"
},
{
"required": true,
"file": "commands/CheckAppealCommand.php"
},
{
"required": true,
"file": "commands/CreateInviteCommand.php"
},
{
"required": true,
"file": "commands/FinalVerdictCommand.php"
},
{
"required": true,
"file": "commands/GenericmessageCommand.php"
},
{
"required": true,
"file": "commands/HelpCommand.php"
},
{
"required": true,
"file": "commands/LanguageCommand.php"
},
{
"required": true,
"file": "commands/LCommand.php"
},
{
"required": true,
"file": "commands/LogCommand.php"
},
{
"required": true,
"file": "commands/MsgInfoCommand.php"
},
{
"required": true,
"file": "commands/NewchatmembersCommand.php"
},
{
"required": true,
"file": "commands/OpdemoteCommand.php"
},
{
"required": true,
"file": "commands/OppromoteCommand.php"
},
{
"required": true,
"file": "commands/PredictionsCommand.php"
},
{
"required": true,
"file": "commands/PropCommand.php"
},
{
"required": true,
"file": "commands/ResetCacheCommand.php"
},
{
"required": true,
"file": "commands/ResetPredictionsCommand.php"
},
{
"required": true,
"file": "commands/SettingsCommand.php"
},
{
"required": true,
"file": "commands/StartCommand.php"
},
{
"required": true,
"file": "commands/StatsCommand.php"
},
{
"required": true,
"file": "commands/WhoisCommand.php"
},
{
"required": true,
"file": "SpamProtectionBot.php"
}
],
"files": [
".htaccess",
"commands/help_docs/blacklist_flags.html",
"commands/help_docs/false_detections.html",
"commands/help_docs/help.html",
"commands/help_docs/help.png",
"commands/help_docs/language.html",
"commands/help_docs/msginfo.html",
"commands/help_docs/settings.html",
"commands/help_docs/spam_protection.html",
"commands/help_docs/start.html",
"commands/help_docs/unwanted_users.html",
"commands/help_docs/whois.html",
"main",
"package.json",
"verdict_worker",
"worker"
]
}

252
botsrc/worker Normal file
View File

@ -0,0 +1,252 @@
<?php
/** @noinspection PhpDefineCanBeReplacedWithConstInspection */
/** @noinspection PhpUndefinedClassInspection */
/** @noinspection DuplicatedCode */
/**
* worker is the code that the worker will execute whenever a job passed on from the main
* bot. Starting the CLI will restart the workers that are already running in the background
*/
use BackgroundWorker\BackgroundWorker;
use CoffeeHouse\CoffeeHouse;
use DeepAnalytics\DeepAnalytics;
use Longman\TelegramBot\Entities\ServerResponse;
use Longman\TelegramBot\Entities\Update;
use Longman\TelegramBot\TelegramLog;
use Longman\TelegramBot\Request;
use ppm\ppm;
use SpamProtection\SpamProtection;
use TelegramClientManager\TelegramClientManager;
use VerboseAdventure\Abstracts\EventType;
use VerboseAdventure\Classes\ErrorHandler;
use VerboseAdventure\VerboseAdventure;
// Import all required auto loaders
/** @noinspection PhpIncludeInspection */
require('ppm');
/** @noinspection PhpUnhandledExceptionInspection */
ppm::import('net.intellivoid.spam_protection_bot');
$current_directory = getcwd();
VerboseAdventure::setStdout(true); // Enable stdout
VerboseAdventure::setSimpleStdout(true); // Simplified output
ErrorHandler::registerHandlers(); // Register error handlers
if(class_exists('SynicalBot') == false)
{
if(file_exists($current_directory . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php'))
{
require_once($current_directory . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php');
}
elseif(file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php'))
{
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php');
}
else
{
throw new RuntimeException('Cannot locate bot class');
}
}
// Load all required configurations
/** @noinspection PhpUnhandledExceptionInspection */
$TelegramServiceConfiguration = SynicalBot::getTelegramConfiguration();
/** @noinspection PhpUnhandledExceptionInspection */
$DatabaseConfiguration = SynicalBot::getDatabaseConfiguration();
/** @noinspection PhpUnhandledExceptionInspection */
$BackgroundWorkerConfiguration = SynicalBot::getBackgroundWorkerConfiguration();
/** @noinspection PhpUnhandledExceptionInspection */
$RedisConfiguration = SynicalBot::getRedisConfiguration();
// Define and create the Telegram Bot instance (SQL)
define('TELEGRAM_BOT_NAME', $TelegramServiceConfiguration['BotName']);
define('LOG_CHANNEL', $TelegramServiceConfiguration['LoggingChannel']);
define('MAIN_OPERATOR_IDS', $TelegramServiceConfiguration['MainOperators']);
SynicalBot::setLogHandler(new VerboseAdventure(TELEGRAM_BOT_NAME));
SynicalBot::setLastWorkerActivity(time());
SynicalBot::setIsSleeping(false);
try
{
if($TelegramServiceConfiguration['EnableCustomServer'])
{
Request::setCustomBotApiUri(
$TelegramServiceConfiguration['CustomEndpoint'],
$TelegramServiceConfiguration['CustomDownloadEndpoint']
);
define('TELEGRAM_ENDPOINT', $TelegramServiceConfiguration['CustomEndpoint']);
define('TELEGRAM_DOWNLOAD_ENDPOINT',
str_ireplace('{API_KEY}', $TelegramServiceConfiguration['BotToken'], $TelegramServiceConfiguration['CustomDownloadEndpoint']));
}
else
{
define('TELEGRAM_ENDPOINT', 'https://api.telegram.org');
define('TELEGRAM_DOWNLOAD_ENDPOINT', '/file/bot' . $TelegramServiceConfiguration['BotToken']);
}
$telegram = new Longman\TelegramBot\Telegram(
$TelegramServiceConfiguration['BotToken'],
$TelegramServiceConfiguration['BotName'],
$TelegramServiceConfiguration['UseTestServers']
);
$telegram->setVerboseLogging($TelegramServiceConfiguration['VerboseLogging']);
if(file_exists($current_directory . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php'))
{
$telegram->addCommandsPaths([$current_directory . DIRECTORY_SEPARATOR . 'commands']);
}
elseif(file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'SpamProtectionBot.php'))
{
$telegram->addCommandsPaths([__DIR__ . DIRECTORY_SEPARATOR . 'commands']);
}
else
{
print('Cannot locate commands path');
exit(1);
}
TelegramLog::initialize();
}
catch (Longman\TelegramBot\Exception\TelegramException $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
exit(255);
}
try
{
$telegram->enableMySql(array(
'host' => $DatabaseConfiguration['Host'],
'port' => $DatabaseConfiguration['Port'],
'user' => $DatabaseConfiguration['Username'],
'password' => $DatabaseConfiguration['Password'],
'database' => $DatabaseConfiguration['Database'],
));
$telegram->enableRedis(
$RedisConfiguration['Host'],
(int)$RedisConfiguration['Port'],
(int)$RedisConfiguration['Database'],
empty($RedisConfiguration['Username']) ? null : $RedisConfiguration['Username'],
empty($RedisConfiguration['Password']) ? null : $RedisConfiguration['Password']
);
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
exit(255);
}
// Start the worker instance
SynicalBot::$DeepAnalytics = new DeepAnalytics();
// Create the database connections
SynicalBot::$TelegramClientManager = new TelegramClientManager();
if(SynicalBot::$TelegramClientManager->getDatabase()->connect_error)
{
SynicalBot::getLogHandler()->log(EventType::ERROR, 'Failed to initialize TelegramClientManager, ' . SynicalBot::$TelegramClientManager->getDatabase()->connect_error, 'Worker');
exit(255);
}
SynicalBot::$SpamProtection = new SpamProtection();
if(SynicalBot::$SpamProtection->getDatabase()->connect_error)
{
SynicalBot::getLogHandler()->log(EventType::ERROR, 'Failed to initialize SpamProtection, ' . SynicalBot::$SpamProtection->getDatabase()->connect_error, 'Worker');
exit(255);
}
SynicalBot::$CoffeeHouse = new CoffeeHouse();
if(SynicalBot::$CoffeeHouse->getDatabase()->connect_error)
{
SynicalBot::getLogHandler()->log(EventType::ERROR, 'Failed to initialize CoffeeHouse, ' . SynicalBot::$CoffeeHouse->getDatabase()->connect_error, 'Worker');
exit(255);
}
try
{
$BackgroundWorker = new BackgroundWorker();
$BackgroundWorker->getWorker()->addServer(
$BackgroundWorkerConfiguration['Host'],
(int)$BackgroundWorkerConfiguration['Port']
);
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
exit(255);
}
// Define the function 'process_batch' to process a batch of Updates from Telegram in the background
$BackgroundWorker->getWorker()->addFunction($telegram->getBotUsername() . '_updates', function(GearmanJob $job) use ($telegram)
{
try
{
/** @noinspection PhpCastIsUnnecessaryInspection */
SynicalBot::setLastWorkerActivity((int)time()); // Set the last activity timestamp
SynicalBot::processSleepCycle(); // Wake worker if it's sleeping
$ServerResponse = new ServerResponse(json_decode($job->workload(), true), TELEGRAM_BOT_NAME);
if(is_null($ServerResponse->getResult()) == false)
{
$UpdateCount = count($ServerResponse->getResult());
if($UpdateCount > 0)
{
SynicalBot::getLogHandler()->log(EventType::INFO, 'Processing ' . $UpdateCount . ' update(s)', 'Worker');
/** @var Update $result */
foreach ($ServerResponse->getResult() as $result)
{
try
{
if(TelegramLog::isVerboseLogging())
SynicalBot::getLogHandler()->log(EventType::INFO, 'Processing update ID ' . $result->getUpdateId(), 'Worker');
$telegram->processUpdate($result);
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
}
}
}
}
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
}
});
// Set the timeout to 5 seconds
$BackgroundWorker->getWorker()->getGearmanWorker()->setTimeout(500);
while(true)
{
try
{
$BackgroundWorker->getWorker()->work(false);
if($BackgroundWorker->getWorker()->getGearmanWorker()->returnCode() == GEARMAN_TIMEOUT)
{
SynicalBot::processSleepCycle();
}
}
catch(Exception $e)
{
SynicalBot::getLogHandler()->logException($e, 'Worker');
exit(255);
}
}