Telegram Bot API:如何清除pending_update_count(CodeIgniter+PHP)
我用CodeIgniter+PHP开发的Telegram机器人今早突然罢工了,查了下发现pending_update_count已经涨到210还一直在往上跳。试了取消重设webhook、换无业务逻辑控制器这些办法都没用,想问问怎么才能把这个待处理计数清掉?
我已经尝试过的方案
- 取消并重新设置webhook:无效,
pending_update_count完全没变化 - 使用无业务逻辑的控制器:还是没用,计数依然持续增长
无业务逻辑控制器代码
class index extends CI_Controller { function __construct() { parent::__construct(); } public function index() { echo('halooo'); $result = 'ok'; return $result; } }
常规处理Telegram消息的代码
class index extends CI_Controller { function __construct() { parent::__construct(); } public function index() { $content = file_get_contents("php://input"); $update = json_decode($content, true); $chatID = $update["message"]["from"]["id"]; $strcmd = trim($update["message"]["text"]); $strMsg = $this->process($strcmd); //process $sendto =API_URL."sendmessage?chat_id=".$chatID."&sendmessage?text=".$strMsg.""; file_get_contents($sendto); } }
我还查了StackOverflow上两个相关的"Clear pending_update_count in Telegram Bot"问题,可惜都没解决我的问题。
亲测有效的解决办法
1. 用getUpdates接口批量拉取丢弃更新
这是最直接的方式,Telegram的getUpdates接口只要调用成功,拉取到的更新就会被标记为已处理(不管你做不做后续处理)。你可以直接用curl命令在终端跑,或者写个简单脚本:
比如curl命令(替换成你的BotToken):
curl "https://api.telegram.org/bot<你的BotToken>/getUpdates?limit=100"
多跑几次,直到返回的结果里result数组为空,这时pending_update_count就会清零了。
2. 临时切换长轮询模式清完所有更新
先关掉webhook,然后循环调用getUpdates拉取所有待处理更新,等计数清0后再重新开启webhook。写个单独的PHP脚本就行(不用集成到CodeIgniter):
<?php $botToken = "你的BotToken"; $apiUrl = "https://api.telegram.org/bot{$botToken}/"; // 先删除webhook file_get_contents($apiUrl . "deleteWebhook"); // 循环拉取直到没有新更新 while (true) { $response = file_get_contents($apiUrl . "getUpdates?limit=100"); $updates = json_decode($response, true); if (empty($updates["result"])) { break; } // 不需要处理,拉取即标记为已处理 sleep(1); } // 可选:重新设置webhook // file_get_contents($apiUrl . "setWebhook?url=你的webhook地址"); echo "待处理更新已全部清除!"; ?>
把这个脚本放服务器上跑一次,基本就能解决问题。
3. 修正你的无业务逻辑控制器响应
Telegram的webhook要求服务器必须返回200 OK的响应,而且要快速(10秒内)。你之前的控制器里return $result在CodeIgniter里是无效的,必须输出内容才能让Telegram收到正确响应。修正后的代码:
class Index extends CI_Controller { function __construct() { parent::__construct(); } public function index() { // 直接输出ok,确保返回200状态码 $this->output->set_status_header(200); $this->output->set_output('ok'); } }
这样Telegram才会认为更新已处理,不会继续堆积。
4. 修复常规处理代码的bug
看你常规处理消息的代码,$sendto的URL里重复了sendmessage,正确的应该是:
$sendto = API_URL . "sendmessage?chat_id=" . $chatID . "&text=" . urlencode($strMsg);
多出来的&sendmessage?会导致发送消息失败,之前的更新可能因为处理失败一直在重试堆积。先把这个bug修好,不然清完计数后还会再出问题。
内容的提问来源于stack exchange,提问作者Ivan

