1. Go to this page and download the library: Download afaztech/reactor-broadcast library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
afaztech / reactor-broadcast example snippets
// app/Providers/AppServiceProvider.php
namespace App\Providers;
use Reactor\Core\Container;
use Reactor\Contracts\ServiceProviderInterface;
use AfazTech\ReactorBroadcast\Support\BroadcastConfig;
class AppServiceProvider implements ServiceProviderInterface
{
public function register(Container $container): void
{
$container->singleton(BroadcastConfig::class, function () {
return (new BroadcastConfig())
->table('users')
->column('user_id')
->onlyActive('status', 1)
->onlyRecent('last_interaction_at', 14)
->queue('broadcast');
});
}
public function boot(Container $container): void
{
}
}
use AfazTech\ReactorBroadcast\Contracts\BroadcastManagerInterface;
$manager = $container->get(BroadcastManagerInterface::class);
$manager->pause($id); // Temporarily halt. Progress is preserved.
$manager->resume($id); // Continue from the first pending recipient.
$manager->cancel($id); // Stop permanently. Already-sent messages are kept.
namespace App\Handlers\Admin;
use Neili\Client;
use Reactor\Attributes\Text;
use Reactor\Attributes\OnUpdate;
use Reactor\Contracts\LanguageInterface;
use Reactor\Contracts\LoggerInterface;
use App\Contracts\Repository\UserRepositoryInterface;
use App\Handlers\BaseHandler;
use AfazTech\ReactorBroadcast\Contracts\BroadcastManagerInterface;
#[Text(name: '/send', isCommand: true, priority: 100)]
#[OnUpdate('message')]
class SendBroadcastHandler extends BaseHandler
{
public function __construct(
Client $client,
LanguageInterface $language,
LoggerInterface $logger,
UserRepositoryInterface $userRepository,
private BroadcastManagerInterface $broadcast,
) {
parent::__construct($client, $language, $logger, $userRepository);
}
protected function handle(array $params = []): void
{
$message = $this->update['message'] ?? [];
$replyTo = $message['reply_to_message'] ?? null;
if (!$replyTo || !isset($replyTo['message_id'])) {
$this->reply(
"Reply to the message you want to broadcast, then send /send."
);
return;
}
try {
$broadcastId = $this->broadcast->start('copy', [
'from_chat_id' => $message['chat']['id'],
'message_id' => (int) $replyTo['message_id'],
]);
} catch (\Throwable $e) {
$this->logger->error('Broadcast start failed', [
'error' => $e->getMessage(),
]);
$this->reply('Failed to start broadcast: ' . $e->getMessage());
return;
}
$stats = $this->broadcast->stats($broadcastId);
$this->reply(
"Broadcast #{$broadcastId} queued.\n"
. "Recipients: {$stats['total']}\n\n"
. "Send /stats {$broadcastId} to watch progress."
);
}
}
namespace App\Handlers\Admin;
use Neili\Client;
use Reactor\Attributes\Text;
use Reactor\Attributes\OnUpdate;
use Reactor\Contracts\LanguageInterface;
use Reactor\Contracts\LoggerInterface;
use App\Contracts\Repository\UserRepositoryInterface;
use App\Handlers\BaseHandler;
use AfazTech\ReactorBroadcast\Contracts\BroadcastManagerInterface;
#[Text(name: '/stats', isCommand: true, priority: 100)]
#[OnUpdate('message')]
class BroadcastStatsHandler extends BaseHandler
{
public function __construct(
Client $client,
LanguageInterface $language,
LoggerInterface $logger,
UserRepositoryInterface $userRepository,
private BroadcastManagerInterface $broadcast,
) {
parent::__construct($client, $language, $logger, $userRepository);
}
protected function handle(array $params = []): void
{
$id = $params[0] ?? null;
if (!is_string($id) || !ctype_digit($id)) {
$this->reply('Usage: /stats <broadcast_id>');
return;
}
try {
$stats = $this->broadcast->stats((int) $id);
} catch (\Throwable $e) {
$this->reply("Broadcast #{$id} not found.");
return;
}
$percent = $stats['total'] > 0
? round(($stats['sent'] + $stats['failed'] + $stats['blocked']) * 100 / $stats['total'], 1)
: 0.0;
$this->reply(
"Broadcast #{$stats['id']}\n"
. "Status: {$stats['status']}\n"
. "Progress: {$percent}%\n\n"
. "Total: {$stats['total']}\n"
. "Sent: {$stats['sent']}\n"
. "Failed: {$stats['failed']}\n"
. "Blocked: {$stats['blocked']}\n"
. "Pending: {$stats['pending']}"
);
}
}
namespace App\Broadcast;
use AfazTech\ReactorBroadcast\Contracts\RecipientProviderInterface;
class ActivePayingUsersProvider implements RecipientProviderInterface
{
public function __construct(private \PDO $pdo) {}
public function count(): int
{
return (int) $this->pdo
->query("SELECT COUNT(*) FROM premium_users WHERE expires_at > NOW()")
->fetchColumn();
}
public function chunk(int $offset, int $limit): array
{
$stmt = $this->pdo->prepare(
"SELECT telegram_id FROM premium_users WHERE expires_at > NOW() ORDER BY telegram_id LIMIT :limit OFFSET :offset"
);
$stmt->bindValue(':limit', $limit, \PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, \PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(\PDO::FETCH_COLUMN);
}
}
use AfazTech\ReactorBroadcast\Contracts\RecipientProviderInterface;
$container->singleton(RecipientProviderInterface::class, function ($c) {
return new \App\Broadcast\ActivePayingUsersProvider($c->get(\PDO::class));
});
bash
php reactor.php migrate
bash
php reactor.php queue:work --queue=broadcast
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.