问题描述
我正在使用Google Apps脚本为我的Telegram机器人创建一个网络应用。机器人通过Web挂钩调用Web应用。
我的机器人有一个嵌入式键盘,您可以在下面的GIF 1中看到它的运行情况。轻按键盘按钮,您将输入一个出现在屏幕上的代码。
我的问题是,当我更快地点击按钮时,对Web应用程序的回调查询发生冲突,从而导致输入混乱。参见GIF 2。
我一直在绞尽脑汁,试图找到一种防止Web应用程序实例冲突的方法,但是到目前为止我还没有运气。
我在下面发布我的代码。请帮助。
我看到的方式是,脚本的每个实例在下一个实例启动之前都需要更多的时间来完成。据我所知,我尝试使用async / await和lockService。已建议我尝试对查询进行排队,但遗憾的是无法使其正常工作。
var lock = LockService.getScriptLock();
function doPost(e){
var contents = JSON.parse(e.postData.contents);
var query_id = contents.callback_query.id;
var mes_id = contents.callback_query.message.message_id;
var userinput = contents.callback_query.data;
var message_Now = contents.callback_query.message.text;
var inline_keyboard = contents.callback_query.message.reply_markup;
var message_upd = message_Now + " " + userinput;
var keydata = {
method: "post",payload: {
method: "editMessageText",chat_id: String(chat_id),message_id: mes_id,text: message_upd,parse_mode: "HTML",reply_markup: JSON.stringify(inline_keyboard)
}
}
lock.waitLock(10000);
UrlFetchApp.fetch('https://api.telegram.org/bot' + token + '/',keydata);
UrlFetchApp.fetch(url + "/answerCallbackQuery?callback_query_id=" + query_id);
lock.releaseLock();
}
解决方法
问题:
我相信lock
确实有效。问题可能是电报bot发送的回调查询。在第二个gif中,
在按2、3和4时,其附加的消息为空。因此,所有4个回调的message.text
将为空
var message_now = contents.callback_query.message.text;
message_now
对于所有4条消息都是空的,并且全部4 mesage_upd
将是不同的:
var message_upd = message_now + " " + userinput;
即使您使用LockService
将所有服务器端排队,如果电报提供的message_now
对于所有4条消息都是空的,排队也无济于事,无法创建这样的串联字符串。
可能的解决方案:
-
对回调进行排队应在客户端完成。仅在收到第一个按钮按下的响应后,才能激活第二个回调。我不确定电报是否可以提供这种精细控制。但是,如果这样做,这是首选的解决方案。
-
使用缓存服务服务器端缓存范围为特定用户的特定
message_now
的最后message.id
。将其保存到缓存服务大约30秒钟。如果30秒钟后出现另一个具有相同message_id的回调,并且message.text为空,请改用缓存的消息。-
key
:某种类型的message_id
和user_id
组合 -
value
:当前串联的message_now
-
摘要:
let message_now = contents.callback_query.message.text;
if (message_now === '') message_now = cache.get(String(mes_id)) || '';
/*....*/
cache.put(String(mes_id),String(message_upd),30);
function doPost(e) {
const lock = LockService.getScriptLock();
lock.waitLock(10000);
const cache = CacheService.getScriptCache();
const contents = JSON.parse(e.postData.contents);
const query_id = contents.callback_query.id;
const mes_id = contents.callback_query.message.message_id;
const userinput = contents.callback_query.data;
let message_now = contents.callback_query.message.text;
if (message_now === '') message_now = cache.get(String(mes_id)) || '';
const inline_keyboard = contents.callback_query.message.reply_markup;
const message_upd = message_now + ' ' + userinput;
const keydata = {
method: 'post',payload: {
method: 'editMessageText',chat_id: String(chat_id),message_id: mes_id,text: message_upd,parse_mode: 'HTML',reply_markup: JSON.stringify(inline_keyboard),},};
UrlFetchApp.fetch('https://api.telegram.org/bot' + token + '/',keydata);
UrlFetchApp.fetch(url + '/answerCallbackQuery?callback_query_id=' + query_id);
cache.put(String(mes_id),30);
lock.releaseLock();
}