others-telegram创建机器人及h5游戏

others-telegram创建机器人及h5游戏


前篇

将机器人的菜单按钮变成打开 h5 游戏


菜单打开 web app

以下的对话都是和官方的机器人 @BotFather 的对话

1. 创建机器人

  1. 输入指令 /newbot 创建, 根据提示输入 机器人昵称, 机器人的 username (唯一 id, 以 bot 结尾)

    image-20240705114729901


2. 设置机器人的 菜单按钮

1. @botfather 中 gui 操作设置
  1. 输入指令 /mybots 选择机器人

    image-20240705113000014

  2. 点击 Bot Settings 进行设置

    image-20240705113056441

  3. 点击 Menu Button 设置菜单

    image-20240705113224186

  4. 点击 Configure menu button 配置菜单

    image-20240705113335615

  5. 按照提示, 输入 h5 游戏的地址

    image-20240705113422582

  6. 设置菜单按钮显示的文字, 这输入 Play Game

    image-20240705113510727

  7. 设置完成, 会提示 Success

    image-20240705113655625

  8. 进入机器人, 可以看到菜单按钮显示上面输入的 Play Game, 点击就可以玩了

    image-20240705113851431


2. @botfather 中指令设置
  • 输入指令: /setmenubutton

    image-20240714164725474


不同平台表现

  • pc 端弹出的窗口很小, 而且是竖屏的, 如果是横屏游戏就不能完, Android 和 iOS 则正常

机器人脚本


go 版本


web app - h5 适配 telegram


需要引入 tg js 库

  1. 引入库

    1
    <script src="https://telegram.org/js/telegram-web-app.js"></script>

设置全屏

  • 默认是拉起 web app 是半屏, 一下 api 可以设置为全屏

    1
    2
    3
    4
    const tg = window.Telegram.WebApp;
    // 先初始化, 再全屏设置
    tg.ready();
    tg.expand();

关闭时二次确认框

  • 默认关闭会直接关掉游戏, 可以设置关闭时弹框二次确认, 防止误点

    1
    2
    3
    const tg = window.Telegram.WebApp;
    // 关闭时二次确认
    tg.isClosingConfirmationEnabled = true;

start 指令带参数跳转

浏览器拉起 tg 传参

  • 拉起 tg 机器人传参必须是在通过 start 参数传递, 也就是会自动输入 /start 命令给机器人, 例如拉起链接: https://t.me/aaa_bot?start=abc, 机器人脚本就能获取到参数 abc, 例如 go 版本:

    start 参数长度的限制是 64

    1
    2
    3
    4
    5
    6
    // 链接跳转必须是 start 指令, 也只有这里能带参数
    b.Handle("/start", func(ctx tb.Context) error {
    args := ctx.Args()
    txt := args[0] // 第一个参数就是 abc
    ...
    }

tg 机器人拉取 web app 传参

  • 在 tg 机器人的 web app 中打开一个游戏地址并带上参数, 例如: https://aaa.bbb.com/index.html?x=1&y=2, 可能会出现获取不到参数 x=1&y=2, 同时报错 Script Error

  • 解决办法: 通过增加一个跳转页 jump.html, 里面获取到参数并重定向到目标网页, 如:

    1
    2
    3
    4
    <script>
    var match = window.location.href.match(/\?(.*)/);
    window.location.href = `https://aaa.bbb.com/index.html?${match != undefined ? match[1] : ""}`
    </script>

设置描述文字及图片

  • 在 @BotFather 中设置

    image-20240713161802127

  • 设置完打开机器人就可以看到描述文字及图片

    image-20240713162604579


web app

bot 按钮链接 和 web app 消息两种形式打开的都是 web app, 同个域下的缓存一样的.

  • @BotFather 使用 /newapp 指令一步步走, 最后会让你输入一个 web 地址就完成, 创建后的链接 https://t.me/aaa_bot/apple001

    • aaa_bot 是机器人 id
    • apple001 就是 web app

    直接通过这个链接就可以拉起 web app, 也就是一个网页

  • 然后再网页中引入 js 库, 就能获取到 telegram 的数据

    1
    <script src="https://telegram.org/js/telegram-web-app.js"></script>
  • 效果

    image-20240714142249726


与 bot 里面指令响应的 web app 区别

  • 打开方式: /newapp 生成的 web app 可以直接通过地址打开, 不需要 bot server; 而 bot 里面的需要发指令, 等 bot server 返回地址后点击才能打开
  • 分享: /new app 生成的 web app 可以分享给其他人, 自己和其他人点击 Launch 就可以开始玩; 而 bot 里面的分享后, 游戏按钮会消失掉, 所以 bot 里面的只能自己玩, 但是可以 通过分享 bot 的链接带上 start 指令, 这样别人就能点击链接跳转到 bot 并自动输入 start 指令, bot server 再响应回复游戏按钮.
  • url 参数: /new app 生成的 web app 的参数是 ??startapp=abcabcabc_ddd; bot 里面的是 ?start=abcabcabc_ddd

app 获取 url 参数

  • https://core.telegram.org/bots/webapps#direct-link-mini-apps

  • 需要在已用后面, 添加参数以 startapp 开头, 例如: https://t.me/aaa_bot/apple001?startapp=abcabcabc_ddd, 可以通过 window.Telegram.WebApp.initData 获取到

    startapp 参数长度的限制是 64

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <script>
    const tg = window.Telegram.WebApp;
    // 先初始化, 再全屏设置
    tg.ready();
    tg.expand();

    console.log('--- initData 01:', tg.initData)
    var initData = decodeURIComponent(tg.initData) // url 需要 decode 一下
    console.log('--- initData 02:', initData)
    // 接收者打开:
    // user={"id":111111,"first_name":"aaa","last_name":"bbb","username":"aaabbb","language_code":"en","allows_write_to_pm":true}&chat_instance=-2338032765734580637&chat_type=private&start_param=abcabcabc_ddd&auth_date=1720893258&hash=fbf027ee6b703a90dca0733465d78960f26e6220635305ce639a4371e5b2d8e2
    </script>
    • start_param 字段里就是 startapp 的参数

获取参数大坑

  • 假如 web app 地址带上参数 ?a=1&tg=1&xxx=2&yyy=3

    在 web app 实际获取到参数转成 object, 第一个参数 a=1 会丢失, 跑到了 tgWebAppThemeParams 里面, 后面的参数就正常

    1
    {"tgWebAppStartParam": "hello#tgWebAppData=user=%7B%22id%22%3A6133686460%2C%22first_name%22%3A%22Terry%22%2C%22last_name%22%3A%22Ronaldo%22%2C%22username%22%3A%22terry996888%22%2C%22language_code%22%3A%22hi%22%2C%22allows_write_to_pm%22%3Atrue%7D", "chat_instance": "1736484854111007021", "chat_type": "private", "start_param": "hello", "auth_date": "1726116556", "hash": "cf60b6d52f354ad0d535964e86e2eab2159c74f1036165fbaf683a2ba7824337", "tgWebAppVersion": "7.10", "tgWebAppPlatform": "tdesktop", "tgWebAppThemeParams": "{"accent_text_color":"#168acd","bg_color":"#ffffff","bottom_bar_bg_color":"#ffffff","button_color":"#40a7e3","button_text_color":"#ffffff","destructive_text_color":"#d14e4e","header_bg_color":"#ffffff","hint_color":"#999999","link_color":"#168acd","secondary_bg_color":"#f1f1f1","section_bg_color":"#ffffff","section_header_text_color":"#168acd","section_separator_color":"#e7e7e7","subtitle_text_color":"#999999","text_color":"#000000"}?a=1", "tg": "1", "xxx": "2", "yyy": "3"}
    • 猜测 tg 是通过 & 分割参数

检验 web app 获取到的数据


手势操作上下滑动会关闭窗口

  • 这个问题暂时存在, 不过高版本 (7.7) 的 tg api 已经支持禁止上下互动关闭窗口.

h5 game


分享


机器人回复带上 app 链接

  • 效果

    image-20240714150739368

    • 这种指令回复可以单上 app 链接, 点击 Launch 就可以玩, 需要注意怎么去拼接 app 参数

    • 这种回复分享后, 别人那虽然虽 内联按钮 消失了, 但还是可以点击 app 的 Launch 玩游戏

      image-20240714150933877


频道内联查询

也就是在频道中, @机器人 的时候可以实时发送到 bot server 查询输入, 并返回结果, 点击结果做出响应

  1. 进机器人内联到频道中, 在 @botfather 中输入: /setinline, 然后输入提示文字就完了

    image-20240714193027707

  2. bot server 处理查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // 处理用户在内联模式下的查询。当用户在聊天中输入 @YourBotUsername 后跟随查询内容时,机器人将返回相关的内联查询结果
    bot.Handle(tb.OnQuery, func(ctx tb.Context) error {
    query := ctx.Query()
    user := query.Sender
    log.Printf("--- OnQuery, query: %+v\n user: %+v\n", query, user)

    // 创建一个按钮
    button := tb.InlineButton{
    Unique: "example_button",
    Text: "Click Me",
    URL: "https://example.com",
    }

    // 创建一个内联查询结果
    result := &tb.ArticleResult{
    Title: "Example",
    Description: "This is an example with a button",
    Text: "<b>Example</b>",
    }
    result.SetResultID(query.ID)
    result.ReplyMarkup = &tb.ReplyMarkup{
    InlineKeyboard: [][]tb.InlineButton{
    {button},
    },
    }

    // 回应内联查询
    return ctx.Answer(&tb.QueryResponse{
    Results: []tb.Result{result},
    CacheTime: 60,
    })
    })
  3. 在频道中 @机器人 就能看到提示, 输入内容就可以有对应的返回了

    image-20240714193539752


游戏

在 2022 年 4 月前,你只能通过 Bot 来创建一个 Game 来将游戏内容化。

在 2022 年 4 月后,Telegram Web App (Mini App) 发布了,你还可以使用 Mini App 的形式来运行和构建游戏。


其他

  • 备注 01

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    频道
    chat_instance: "2875149934213931879"
    chat_type: "channel"

    私聊
    chat_instance: "-2338032765734580637"
    chat_type: "private"

    机器人菜单
    query_id: "AAGDOJc-AAAAAIM4lz7os2_l"

踩坑

iOS 跳转网页无反应

  • 调用 js 跳转网页的 api 如: window.open("https://www.google.com/", "_blank") 没有反应

  • 原因是因为 iOS 平台的跳转, 必须在用户点击手势触发的那一帧中进行跳转; 如果用户点击后使用了异步代码, 跳帧后才去调用跳转接口, 则没有反应. 这个现象和 触发全屏 的接口一样的情况

    Android 端则没有这个问题


拼接上参数打不开游戏

  • 在游戏地址后面通过 ? 拼接参数后无法进入游戏, 报错 Script Error

  • 解决办法: 在同域名下创建一个 aaa.html 跳转页, 获取到 url 上的参数然后重定向到目标游戏地址即可, 在 telegram 上配置地址的时候就配 aaa.html 跳转页, 如:

    1
    2
    var match = window.location.href.match(/\?(.*)/);
    window.location.href = `../index.html?${match != undefined ? match[1] : ""}`