2

0. 简介

近两年tg的小程序也在不断兴起,能力不断增加,有变成微信小程序这种“超级应用”的趋势,所以近期准备深入浅出的了解一下。但在浏览简陋的官方文档时看它在篇幅的最开始提及,目前的Mini Apps还是强依赖于Telegram Bot,遂决定本次先从Bot入手。

Telegram Mini Apps is a technology created by developers of the famous messenger Telegram. The main it’s purpose is to provide developers more flexible communication channel with Telegram users.

It may seem not clear, but Mini Apps are not self-served services. The first thing to note is, technically, this technology is just an add-on for such already-known Telegram functionality as Telegram Bots. So, currently, creating a Mini App without creating a Telegram Bot is not available.

1. 注册Bot

做Bot开发,肯定需要现有一个Bot。推荐大家先使用测试环境进行开发,会少很多限制,切换测试环境的方法详见官方文档

在切换完环境后(换不换的流程都一样)在Contracts里搜索@botfather(注意会有很多个假的, 一字不差的才是真的)。
@botfather

进入之后发送/start,会自动回复很多可用命令。
/start

创建Bot就使用/newbot命令,我们就根据提示输入Bot的名字和ID,注意这里的ID将会是全服务器唯一ID,并且会在注册成功后会返回一个token,这个token将会是我们未来请求tg的唯一凭证,可以记下来并且保存好,不要轻易泄露给他人。
/newbot

2. 依赖

为了快速上手,我们本次使用node-telegram-bot-api库进行开发。

安装

npm i node-telegram-bot-api

使用

const TelegramBot = require('node-telegram-bot-api');

// replace the value below with the Telegram token you receive from @BotFather
const token = 'YOUR_TELEGRAM_BOT_TOKEN';

// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, {polling: true});

// Matches "/echo [whatever]"
bot.onText(/\/echo (.+)/, (msg, match) => {
  // 'msg' is the received Message from Telegram
  // 'match' is the result of executing the regexp above on the text content
  // of the message

  const chatId = msg.chat.id;
  const resp = match[1]; // the captured "whatever"

  // send back the matched "whatever" to the chat
  bot.sendMessage(chatId, resp);
});

// Listen for any kind of message. There are different kinds of
// messages.
bot.on('message', (msg) => {
  const chatId = msg.chat.id;

  // send a message to the chat acknowledging receipt of their message
  bot.sendMessage(chatId, 'Received your message');
});

3. 基础指令

可以看到已经写了最基础的使用方法,我们依照教程新建一个index.ts,引入依赖替换我们的token,并写一个最简单的/ping命令,在接收到时返回一个pong

// index.ts
const TelegramBot = require('node-telegram-bot-api');
const token = 'TOKEN';

const bot = new TelegramBot(token, {
  polling: true,
  testEnvironment: true
});

bot.onText(/\/ping/, (msg) => {
  const chatId = msg.chat.id;

  bot.sendMessage(chatId, 'pong');
});

然后直接运行

$ node ./index.ts

4. 魔法(没有上述问题的可以跳过本节)

不出意外的话,是要出意外了。

error: [polling_error] {"code":"EFATAL","message":"EFATAL: Error: connect ETIMEDOUT 45.114.11.25:443"}

刚刚执行的Node会直接报错,控制台的报错很好理解,就是请求超时了。道理也很简单,tg本来就是在国内不可用的,Bot相关的服务也必不可能直接调用。

这里需要大家自备一个魔法工具,但简单尝试一下会发现就算开启了全局模式也不能解决问题,我们这里直接说解决方案,就是根据自己的魔法工具选择引入响应的代理库,例如socks-proxy-agentsocks5-http-clientsocks5-https-client等,区别视自己的魔法类型而定。

这里以v2rN为例,在魔法工具里设置好【本地socks监听端口】,安装socks-proxy-agent并引入依赖,然后在实例化的时候配置自己的socks监听端口地址,并在TelegramBot的实例化中引入方法。

// index.ts
const TelegramBot = require('node-telegram-bot-api');
const { SocksProxyAgent } = require('socks-proxy-agent');

// 在实例化的时候填入自己的socks地址
const agent = new SocksProxyAgent('socks://localhost:10808')
const token = 'TOKEN';

const bot = new TelegramBot(token, {
  polling: true,
  testEnvironment: true,
  request: {
    agent
  }
});

bot.onText(/\/ping/, (msg) => {
  const chatId = msg.chat.id;

  bot.sendMessage(chatId, 'pong');
});

再运行当前文件,就不会有连接超时的报错(其他报错可能是魔法库在实例化的时候用法错误,可以去看TelegramBot的源码和各个魔法库的实现方法),在tg里给自己发消息,也可以收到相应回复了。

/ping

5. 读取消息

刚刚我们只是实现了在收到指令时作出相应,我们希望进一步开发我们的Bot,可以根据指令后的内容做出响应回复,那不妨来做一个最简单的复读。

bot.onText(/\/repeat (.+)/, (msg, match) => {
  const chatId = msg.chat.id;
  const text = match[1];

  bot.sendMessage(chatId, text);
});

/repeat

6. 列表

只是通过输入命令来做出响应还是有点麻烦,我们希望可以通过一个命令列出来所有的命令,并让我们挨个选择,这里就可以用上reply_markupinline_keyboard字段

bot.onText(/\menu/, (msg) => {
  const chatId = msg.chat.id;
  bot.sendMessage(chatId, "Here's your menu:", {
    reply_markup: {
      inline_keyboard: [
        [{
          text: 'ping',
          callback_data: JSON.stringify({ command: 'ping' })
        }],
        [{
          text: 'date',
          callback_data: JSON.stringify({ command: 'date' })
        }],
      ],
    },
  });
})

这样我们就可以通过/menu获得一个有ping和date命令的菜单

/menu

但是目前这个菜单仅能显示,不具备任何功能,所以我们需要对刚刚在定义两个功能时的callback做出相应处理

bot.on('callback_query', (callbackQuery) => {
  const data = JSON.parse(callbackQuery.data);

  if (data.command === 'ping') {
    bot.answerCallbackQuery(callbackQuery.id, { text: 'pong' });
  }

  if (data.command === 'date') {
    bot.answerCallbackQuery(callbackQuery.id, { text: new Date().toLocaleString() });
  }

});

7. 菜单

仅仅是通过/menu操作还是有一定的难度,万一用户连这个命令都不知道该怎么办?这个时候我们就可以找老朋友@BotFather通过/setcommands命令来给我们的Bot注册菜单

/setcommands

这样一来我们的Bot聊天页面左下角的菜单里,就会出现我们刚刚注册的/ping命令,点击后也可以自动发送并受到相应地响应。

image.png

如此一来,我们就已经完成了Telegram Bot的基础建设,更多功能可以自行查阅官方文档并调研,感谢观看!


Andarinz
15 声望4 粉丝