C# 中的 Telegram Bot 自定义键盘

Posted

技术标签:

【中文标题】C# 中的 Telegram Bot 自定义键盘【英文标题】:Telegram Bot custom keyboard in C# 【发布时间】:2016-04-26 06:33:59 【问题描述】:

我尝试使用自定义键盘创建消息。所以我发送请求

reply_markup = "keyboard":[["1"],["2"]],"resize_keyboard":"True","one_time_keyboard":"True"

但是,它不起作用。

我尝试了所有的 Content-Type:

    application/x-www-form-urlencoded(使用默认创建消息 键盘) application/json(使用默认键盘创建消息) multipart/form-data(根本不起作用,尽管this Post)

我还尝试通过 2 种不同的方式发送消息。这段代码有什么问题?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;

namespace DutyReminder

class Program

    static void Main(string[] args)
    

        string message = "message";
        string message1 = "message1";
        string botid = "165749848:AAGtjn42bajF-WxdKosTF07sLwJPYlqiDZE";
        string chatid = "38651047";

        Sender.send("", "https://api.telegram.org/bot" + botid + "/sendmessage?chat_id=" + chatid + "&text=" + message + "&reply_markup=\"keyboard\":[[\"1\"],[\"2\"]],\"resize_keyboard\":\"True\",\"one_time_keyboard\":\"True\"");
        Sender.HttpPost("https://api.telegram.org/bot" + botid + "/sendmessage?chat_id=" + chatid + "&text=" + message1 + "&reply_markup=\"keyboard\":[[\"1\"],[\"2\"]],\"resize_keyboard\":\"True\",\"one_time_keyboard\":\"True\"", "");

    


static class Sender

    static public void send(string message, string url)
    
        // Create a request using a URL that can receive a post. 
        WebRequest request = WebRequest.Create(url);
        // Set the Method property of the request to POST.
        request.Method = "POST";
        // Create POST data and convert it to a byte array.
        //string postData = "\"value1\":\"" + message + "\"";
        string postData = message;
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        // Set the ContentType property of the WebRequest.
        request.ContentType = "application/x-www-form-urlencoded";
        // Set the ContentLength property of the WebRequest.
        //  request.ContentLength = byteArray.Length;
        // Get the request stream.
        Stream dataStream = request.GetRequestStream();
        // Write the data to the request stream.
        dataStream.Write(byteArray, 0, byteArray.Length);
        // Close the Stream object.
        dataStream.Close();
        // Get the response.
        WebResponse response = request.GetResponse();
        // Display the status.
        Console.WriteLine(((HttpWebResponse)response).StatusDescription);
        // Get the stream containing content returned by the server.
        dataStream = response.GetResponseStream();
        // Open the stream using a StreamReader for easy access.
        StreamReader reader = new StreamReader(dataStream);
        // Read the content.
        string responseFromServer = reader.ReadToEnd();
        // Display the content.
        Console.WriteLine(responseFromServer);
        // Clean up the streams.
        reader.Close();
        dataStream.Close();
        response.Close();
    


    static public string HttpPost(string URI, string Parameters)
    
        System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
      //  req.Proxy = new System.Net.WebProxy(ProxyString, true);
        //Add these, as we're doing a POST
        req.ContentType = "application/x-www-form-urlencoded";
        req.Method = "POST";
        //We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
        byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
        req.ContentLength = bytes.Length;
        System.IO.Stream os = req.GetRequestStream();
        os.Write(bytes, 0, bytes.Length); //Push it out there
        os.Close();
        System.Net.WebResponse resp = req.GetResponse();
        if (resp == null) return null;
        System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
        return sr.ReadToEnd().Trim();
    



【问题讨论】:

你得到什么错误?也许您应该在代码中添加 try-catch-Blocks 以获得详细的错误消息。 没有错误,但是也没有自定义键盘f6.s.qip.ru/echeMYh9.png 好像是电报忽略reply_markup参数。 那么你得到了什么回应?我想,第一个问题是,是通信问题还是指挥问题。 我得到响应:"ok":true,"result":"message_id":65,"from":"id":165749848,"first_name":"Duty","用户名":"DutyBot","chat":"id":38651047,"first_name":"\u0413\u0440\u0438\u0448\u0430","type":"private","date":1453290235 ,"text":"message1" 如果将使用request.ContentType = "multipart/form-data" 作为推荐的here,则不会发送任何消息,我将一无所获。 我找到了问题的解决方案。我应该使用 "resize_keyboard\":\"true\" 而不是 resize_keyboard\":\"True\"。 【参考方案1】:

使用以下代替 URI 消息发送:

var bot = new Api("YourApiToken");
.
.
.

var rmu = new ReplyKeyboardMarkup();

rmu.Keyboard =
    new string[][]
    
        new string[] "1-1", "1-2",
        new string[] "2",
        new string[] "3-1", "3-2" , "3-3" 
    ;

await bot.SendTextMessage(update.Message.Chat.Id, msg, false, 0, rmu);

更新 使用较新版本的 API:

var bot = new Api("YourApiToken");
.
.
.

var rkm = new ReplyKeyboardMarkup();

rkm.Keyboard = 
    new KeyboardButton[][]
    
        new KeyboardButton[]
        
            new KeyboardButton("1-1"),
            new KeyboardButton("1-2")
        ,

        new KeyboardButton[]
        
            new KeyboardButton("2")
        ,

        new KeyboardButton[]
        
            new KeyboardButton("3-1"),
            new KeyboardButton("3-2"),
            new KeyboardButton("3-3")
        
    ;

await bot.SendTextMessage(update.Message.Chat.Id, msg, false, false, 0, rkm );

【讨论】:

@Grisha,输入Nuget 输入Install-Package Telegram.Bot @SiyavashHamdi : ***.com/questions/39884961/…【参考方案2】:

您可以动态创建键盘。

var rkm = new ReplyKeyboardMarkup();
var rows = new List<KeyboardButton[]>();
var cols = new List<KeyboardButton>();
for (var Index = 1; Index < 17; Index++)

    cols.Add(new KeyboardButton("" + Index));
    if (Index%4 != 0) continue;
    rows.Add(cols.ToArray());
    cols = new List<KeyboardButton>();

rkm.Keyboard = rows.ToArray();


await botClient.SendTextMessageAsync(
    message.Chat.Id,
    "Choose",
    replyMarkup: rkm);

【讨论】:

【参考方案3】:

我是按我的方式做的:)

public static class KeyboardHelper

        public static ReplyKeyboardMarkup GetKeyboard(List<string> keys)
        
            var rkm = new ReplyKeyboardMarkup();
            var rows = new List<KeyboardButton[]>();
            var cols = new List<KeyboardButton>();
            foreach (var t in keys)
            
                cols.Add(new KeyboardButton(t));
                rows.Add(cols.ToArray());
                cols = new List<KeyboardButton>();
            
            rkm.Keyboard = rows.ToArray();
            return rkm;
        

【讨论】:

【参考方案4】:
List<string> items = new List<string>();

items.Add("A");
items.Add("B");
items.Add("C");
items.Add("D");
items.Add("E");                               
                                  

var rkm = new ReplyKeyboardMarkup();
var rows = new List<KeyboardButton[]>();
var cols = new List<KeyboardButton>();   
for (var Index = 1; Index < items.Count+1; Index++)

   cols.Add(new KeyboardButton("" + items[Index-1]));
   if (Index % 4 != 0) continue;
   rows.Add(cols.ToArray());
   cols = new List<KeyboardButton>();


    
if (cols.Count > 0) rows.Add(cols.ToArray());

rkm.Keyboard = rows.ToArray();
await Bot.SendTextMessageAsync(message.Chat.Id,"Choose",replyMarkup: rkm);

【讨论】:

虽然这可能会回答这个问题,但如果可能的话,您应该edit 回答您的回答,以包含对如何此代码块回答问题的解释。这有助于提供上下文,并使您的答案对未来的读者更有用。

以上是关于C# 中的 Telegram Bot 自定义键盘的主要内容,如果未能解决你的问题,请参考以下文章

带有自签名证书的 Telegram bot webhook 不起作用

python Webhook使用自签名证书和Flask(使用python-telegram-bot库)

python Webhook使用自签名证书和Flask(使用python-telegram-bot库)

Telegram API vs Bot API [关闭]

Django 查询 - 将用户类与 Telegram Bot 的 OnetoOnefield 类连接起来

如何在 C# 中处理 Telegram bot 上的多个用户?