需要防止GAS网络应用实例冲突 问题:可能的解决方案:摘要:参考文献:

问题描述

我正在使用Google Apps脚本为我的Telegram机器人创建一个网络应用。机器人通过Web挂钩调用Web应用。

我的机器人有一个嵌入式键盘,您可以在下面的GIF 1中看到它的运行情况。轻按键盘按钮,您将输入一个出现在屏幕上的代码

我的问题是,当我更快地点击按钮时,对Web应用程序的回调查询发生冲突,从而导致输入混乱。参见GIF 2。

我一直在绞尽脑汁,试图找到一种防止Web应用程序实例冲突的方法,但是到目前为止我还没有运气。

我在下面发布我的代码。请帮助。

我看到的方式是,脚本的每个实例在下一个实例启动之前都需要更多的时间来完成。据我所知,我尝试使用async / await和lockService。已建议我尝试对查询进行排队,但遗憾的是无法使其正常工作。

GIF 1

GIF 2

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_iduser_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();
}

参考文献: