InlineKeyboardButton are limited in InlineKeyboardMarkup ? telegram bot C#

Viewed 6821

I Use C# and telegram.bot and want create dynamic InlineKeyboardMarkup

private static InlineKeyboardMarkup InlinePostsKeyboard;
private static List<string> PostsTitle;
...
PostsTitle = (from p in dba.BlogPosts select p.Subject).Take(4).ToList();

var inlineButtons = PostsTitle.Select(title => new[] { InlineKeyboardButton.WithCallbackData(title, title) }).ToArray();
InlinePostsKeyboard = new InlineKeyboardMarkup(inlineButtons);

...
Bot.SendTextMessageAsync(Chat.Id, e.Message.Text, replyMarkup: InlinePostsKeyboard);`

as you see in above code bot most show 4 InlineKeyboardButton (per line) , but does not show anything ! Just enough change ....Take(4).ToList(); to 3 or less than 4 (ex : 3 , 2 or 1) and you will see that the buttons will be displayed correctly

I want to know the reason for this Where have I made a mistake?

2 Answers

If there is a limit on number of inline keyboard rows/buttons it is definitely more than 3.

Log & check what you are sending to Telegram API. I suspect one of your blog post p.Subject return empty string or too long string or something that Telegram does not allow.

Also make sure the library you are using does escape values properly (e.g. replaces special characters like ")

By the way, why would you pass post subject as callback_data? Would not it be better to pass post ID as something like post?id=123?

In one button row you can fit a maximum of 8 buttons. If you have more than 8 buttons, you have to put them into multiple rows.

I've written a (TypeScript) utility function to split the buttons array:

evenlySplitArray<T>(arrayToSplit: T[]): T[][] {
  if (!Array.isArray(arrayToSplit)) {
    return [[]];
  }

  const length = arrayToSplit.length;
  // Last row can contain one element more.
  const maxElementsPerRow = 5;
  const numberOfRows = Math.ceil(length / maxElementsPerRow);
  const elementsPerRow = Math.round(length / numberOfRows);

  const result = [];
  for (let i = 0; i < numberOfRows; i++) {
    // Add remainder to last row
    const end = i === numberOfRows - 1 ? length : (i + 1) * elementsPerRow;
    const split = arrayToSplit.slice(i * elementsPerRow, end);
    result.push(split);
  }
  return result;
}

The limit on the callback_data is 1-64 bytes, e.g. a JWT does not fit.

Related