Files

174 lines
10 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/** @var string $page_slug */
/** @var string $nonce */
$last_test = \Cf7stg\Settings::get_last_test();
$pending = \Cf7stg\Queue::count_by_status(\Cf7stg\Queue::STATUS_PENDING);
$sent24 = \Cf7stg\Queue::count_sent_last_24h();
$failed = \Cf7stg\Queue::count_failed();
$notice = '';
if (!empty($_GET['saved'])) $notice = '<div class="notice notice-success"><p>Настройки сохранены.</p></div>';
if (($_GET['test'] ?? '') === 'ok') $notice = '<div class="notice notice-success"><p>Тестовое сообщение отправлено.</p></div>';
if (($_GET['test'] ?? '') === 'err') $notice = '<div class="notice notice-error"><p>Ошибка отправки: ' . esc_html($last_test['err'] ?? '') . '</p></div>';
if (isset($_GET['retro_added'])) $notice = '<div class="notice notice-success"><p>Добавлено в очередь: ' . (int)$_GET['retro_added'] . ', пропущено: ' . (int)$_GET['retro_skipped'] . '.</p></div>';
if (isset($_GET['retried'])) $notice = '<div class="notice notice-success"><p>Перезапущено с ошибкой: ' . (int)$_GET['retried'] . '.</p></div>';
if (isset($_GET['purged'])) $notice = '<div class="notice notice-success"><p>Удалено отправленных: ' . (int)$_GET['purged'] . '.</p></div>';
if (isset($_GET['drop_saved'])) $notice = '<div class="notice notice-success"><p>Настройки silent drop сохранены.</p></div>';
if (isset($_GET['drop_reset'])) $notice = '<div class="notice notice-success"><p>Счётчики silent drop сброшены.</p></div>';
?>
<div class="wrap">
<h1>CF7 Spam → Telegram</h1>
<?php echo $notice; ?>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<input type="hidden" name="action" value="cf7stg_save">
<?php wp_nonce_field('cf7stg_save', $nonce); ?>
<h2>Настройки Telegram</h2>
<table class="form-table">
<tr>
<th><label for="bot_token">Bot Token</label></th>
<td>
<?php if (\Cf7stg\Settings::is_bot_token_constant()): ?>
<em>Задано константой <code>SPAM2TG_BOT_TOKEN</code> в wp-config.php (readonly).</em>
<?php else: ?>
<input type="password" id="bot_token" name="bot_token" class="regular-text" autocomplete="off" placeholder="<?php echo \Cf7stg\Settings::get_bot_token() ? '(сохранён)' : ''; ?>">
<p class="description">Можно задать константой <code>SPAM2TG_BOT_TOKEN</code> в wp-config.php вместо БД.</p>
<?php endif; ?>
</td>
</tr>
<tr>
<th><label for="chat_id">Chat ID</label></th>
<td>
<?php if (\Cf7stg\Settings::is_chat_id_constant()): ?>
<em>Задано константой <code>SPAM2TG_CHAT_ID</code> (readonly).</em>
<?php else: ?>
<input type="text" id="chat_id" name="chat_id" class="regular-text" value="<?php echo esc_attr(\Cf7stg\Settings::get_chat_id()); ?>">
<?php endif; ?>
</td>
</tr>
<tr>
<th><label for="site_title">Заголовок сайта</label></th>
<td>
<input type="text" id="site_title" name="site_title" class="regular-text" value="<?php echo esc_attr((string)get_option(\Cf7stg\Settings::OPT_SITE_TITLE, '')); ?>" placeholder="<?php echo esc_attr(\Cf7stg\Settings::get_site_title()); ?>">
<p class="description">Если пусто — используется домен (декодированный из Punycode).</p>
</td>
</tr>
</table>
<?php submit_button('Сохранить настройки'); ?>
</form>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin-top:16px">
<input type="hidden" name="action" value="cf7stg_test">
<?php wp_nonce_field('cf7stg_test', $nonce); ?>
<button type="submit" class="button">Отправить тестовое сообщение</button>
<?php if (!empty($last_test)): ?>
<span style="margin-left:12px">
<?php if (!empty($last_test['ok'])): ?>
✅ Последняя проверка: <?php echo esc_html((string)$last_test['at']); ?> — OK
<?php else: ?>
⚠️ Последняя проверка: <?php echo esc_html((string)$last_test['at']); ?> — <?php echo esc_html((string)$last_test['err']); ?>
<?php endif; ?>
</span>
<?php endif; ?>
</form>
<hr>
<h2>Ретроспективная выгрузка из Flamingo</h2>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<input type="hidden" name="action" value="cf7stg_retro">
<?php wp_nonce_field('cf7stg_retro', $nonce); ?>
<table class="form-table">
<tr>
<th>Количество записей</th>
<td><input type="number" name="retro_count" value="10" min="1" max="50"> <span class="description">макс. 50</span></td>
</tr>
<tr>
<th>Только за последние</th>
<td><input type="number" name="retro_days" value="0" min="0"> дней <span class="description">(0 = без ограничения)</span></td>
</tr>
<tr>
<th>&nbsp;</th>
<td><label><input type="checkbox" name="retro_repeat" value="1"> Разрешить повтор уже отправленных</label></td>
</tr>
</table>
<?php submit_button('Добавить в очередь', 'secondary'); ?>
</form>
<hr>
<h2>Состояние очереди</h2>
<p>В очереди (ожидают): <b><?php echo (int)$pending; ?></b> · Отправлено за сутки: <b><?php echo (int)$sent24; ?></b> · С ошибками: <b><?php echo (int)$failed; ?></b></p>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline-block;margin-right:8px">
<input type="hidden" name="action" value="cf7stg_retry_failed">
<?php wp_nonce_field('cf7stg_retry_failed', $nonce); ?>
<button type="submit" class="button">Повторить все ошибочные</button>
</form>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline-block">
<input type="hidden" name="action" value="cf7stg_purge_sent">
<?php wp_nonce_field('cf7stg_purge_sent', $nonce); ?>
<button type="submit" class="button">Очистить отправленные</button>
</form>
<hr>
<h2>Silent drop</h2>
<p class="description">
Заявки, удовлетворяющие правилам, не отправляются в Telegram.
Подробности правил — в <code>docs/superpowers/specs/2026-04-21-cf7stg-silent-drop-design.md</code>.
</p>
<?php
$drop_counters = \Cf7stg\Settings::get_drop_counters();
$is_dry = \Cf7stg\Settings::is_dry_run_drop();
?>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<input type="hidden" name="action" value="cf7stg_save_drop">
<?php wp_nonce_field('cf7stg_save_drop', $nonce); ?>
<table class="form-table">
<tr>
<th>Dry-run mode</th>
<td>
<label>
<input type="checkbox" name="dry_run_drop" value="1" <?php checked($is_dry); ?>>
Не дропать реально, отправлять в TG с пометкой «[БЫЛО БЫ DROPPED]»
</label>
<p class="description">Включён по умолчанию. Снимите галочку только убедившись по TG-сообщениям, что среди дропов нет реальных клиентов.</p>
</td>
</tr>
<tr>
<th>Hard-rule override</th>
<td>
<label>
<input type="checkbox" name="hard_drop_enabled" value="1" <?php checked(\Cf7stg\Settings::is_hard_drop_enabled()); ?>>
Включить правило: нет позитивных сигналов + короткое латинское имя или ≥ 3 поля-плейсхолдера
</label>
</td>
</tr>
<tr>
<th><label for="drop_score_threshold">Score-порог drop</label></th>
<td>
<input type="number" id="drop_score_threshold" name="drop_score_threshold" value="<?php echo (int)\Cf7stg\Settings::get_drop_score_threshold(); ?>" step="1">
<p class="description">Дефолт 5. Заявка с score ≤ этого значения дропается даже без hard-rule.</p>
</td>
</tr>
</table>
<?php submit_button('Сохранить silent-drop настройки'); ?>
</form>
<h3>Статистика</h3>
<p>
Всего дропнуто: <b><?php echo (int)$drop_counters['total']; ?></b><br>
Сегодня (real): <b><?php echo (int)$drop_counters['real_today']; ?></b> · сегодня (dry-run): <b><?php echo (int)$drop_counters['dry_today']; ?></b><br>
Вчера (real): <b><?php echo (int)$drop_counters['real_yesterday']; ?></b> · вчера (dry-run): <b><?php echo (int)$drop_counters['dry_yesterday']; ?></b><br>
Счётчик с: <b><?php echo esc_html((string)$drop_counters['reset_at']); ?></b>
</p>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<input type="hidden" name="action" value="cf7stg_reset_drop_counters">
<?php wp_nonce_field('cf7stg_reset_drop_counters', $nonce); ?>
<button type="submit" class="button">Сбросить счётчики</button>
</form>
</div>