← Вернуться к списку тем

Расширение функционала бота обратной связи Google Apps Script + Telegram Bot API

Здравствуйте, возможно ли сделать так, что бы вместе с сообщением пользователя выводились кнопки "ответить" и "забанить", и после нажатия на "ответить", и ответа админа на сообщение кнопка становилась не активной и меняла текст на "ответ отправлен", а после нажатия "забанить" пользователь был бы заблокирован и больше не мог пользоваться ботом? Если возможно, то подскажите в каком направлении двигаться...

В js я еще слабоват, поэтому развернутый ответ был бы очень полезен...

Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.

  • iMakeBots [1 год назад]

    Кнопку приаттачить к сообщению без проблем, нужно или нативно прописывать или же можно также расширить класс Bot, и добавить методы отрисовки кнопки и  набора кнопок: 

    /**
       * Кнопка inline
       * @param text
       * @param callback_data
       * @param url
       * @param switch_inline_query
       * @returns {{text: *}}
       */
      buildInlineKeyboardButton(text, callback_data = null, url = null, switch_inline_query = null) {
        // рисуем кнопке текст
        let replyMarkup = {
          text: text
        };
        // пишем одно из обязательных дополнений кнопке
        if (!isNull(url)) {
          replyMarkup.url = url;
        } else if (!isNull(callback_data)) {
          replyMarkup.callback_data = callback_data;
        } else if (!isNull(switch_inline_query)) {
          replyMarkup.switch_inline_query = switch_inline_query;
        }
        // возвращаем кнопку
        return replyMarkup;
      }
    
      /**
       * Набор кнопок inline
       * @param options
       * @returns {string}
       */
      buildInlineKeyBoard(options) {
        // собираем кнопки
        return JSON.stringify({
          inline_keyboard: options,
        });
      }

    Сделать неактивной inline кнопку не получиться, нет такого функционала, если только повесить на action метод который бы выводил notice "На сообщение уже был ответ", но лучше просто удалить кнопку из набора, через метод класса Bot.

    /**
       * Обновляем клавиатуру
       * @param chat_id
       * @param message_id
       * @param buttons
       * @returns {*}
       */
      editMessageReplyMarkup(chat_id, message_id, buttons) {
        // готовим данные
        let payload = {
          method: "editMessageReplyMarkup",
          chat_id: String(chat_id),
          message_id: String(message_id),
          reply_markup: this.buildInlineKeyBoard(buttons)
        };
        // вернем результат отправки
        return this.query(payload);
      }

    Также можно не менять логику и при нажатии на кнопку "Ответить" подставлять в ответ сообщение через forceReply

    reply_markup: {force_reply: true}

    Для блокировки пользователя, нужно добавить в набор колонок новую колонку ban

    users: {
          table: 'Users',
          uid: 1,
          name: 2,
          userName: 3,
          lang: 4,
          ban: 5,
          created_at: 6,
          updated_at: 7,
        },

    В новой колонке ban храните или 1 (блокирован) или 0 (не блокирован)

    Не забудьте про последовательность нумерации (или можете подсмотреть как сделано в статье про Бот-магазин - там уже ненужно следить за нумерацией). Также нужно в классе User подправить метод save() добавить для новых пользователей пятым значением: 0 

    // если строка не найдена, значит добавляем пользователя в лист
    sheet.appendRow([this.uid, this.name, this.userName, this.lang, 0, date.toString(), date.toString()]);

    Action для кнопки "Забанить" просто блокировка пользователя - в данном примере нужно будет писать что-то похожее на метод save() класса User, уже в Бот-магазине там просто было бы:

    this.wh.user.ban = 1;
    this.wh.user.save();
    
    // =====
    
    // или через метод класса User
    this.wh.user.setBan(1);
    
    /**
     * Устанавливаем статус бана
     * @param type
     */
    setBan(type) {
      this.ban = type;
      this.save();
    }

    В роутере обязательно сделать проверку на бан пользователя

    /**
     * Маршрутизируем
     */
    route() {
      if (this.bot.data.message.chat.type !== 'private') {
        throw new Error('403 - stop');
      }
      // проверка на бан пользователя
      if(this.user.ban) {
        throw new Error('403 - stop auth ban');
      }
      // .....
  • AGM 33rus [1 год назад → iMakeBots]

    Благодарю, очень содержательный ответ, буду разбираться, что к чему...

    Хотелось бы еще узнать: Если пользователь написал сообщение и отправил, а потом удалил это сообщение, возможно ли реализовать удаление этого сообщения или пометить его как удаленное и у админа, так как отвечать на него уже нет необходимости?

  • iMakeBots [1 год назад → AGM 33rus]

    Сам не проверял, но вроде не припомню что бы было техническое сообщение на вебхук при удалении сообщения. Если такое есть то можно подумать.

  • AGM 33rus [1 год назад → iMakeBots]

    Я знаю, что в каналах удаление сообщений возможно, но вот в данном случае не приложу ума как это организовать...

  • iMakeBots [1 год назад → AGM 33rus]

    Удалить сообщение не проблема есть метод deleteMessage() для этого нужен message_id, и событие по которому можно запустить удаление, например если при удалении пользователем сообщения будет событие - уведомление вебхука служебным сообщением - типа удалено сообщение с таким то message_id - тогда можно что-нибудь придумать - а без этого вы просто не узнаете, что оно удалено.

    Если только не делать проверку на существование этого сообщения у пользователя))) (я как-то делал такое в канале)

  • AGM 33rus [1 год назад → iMakeBots]

    Понял, рановато мне еще заострять на это внимание, буду учиться реализовывать что то по проще...

    Еще вопрос, по поводу последовательности заполнения в таблице, как вы относитесь к использованию библиотек? Стоит ли использовать, например вот эту https://www.npmjs.com/package/sheetquery или лучше реализацию выполнять самому в скрипте?

  • iMakeBots [1 год назад → AGM 33rus]

    Я для прокачки своего скилла - сделал что-то похожее и по функционалу минимальное - только то что было нужно мне в проекте, но не брезгую использовать уже готовое - экономит время.

  • AGM 33rus [1 год назад → iMakeBots]

    Ну, уж чего чего, а времени у меня предостаточно...

    Огромное Спасибо...