diff --git a/README.md b/README.md
index 895cb97..dad8183 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Foo](https://img.shields.io/badge/Version-2.15-brightgreen.svg?style=flat-square)](#versions)
+[![Foo](https://img.shields.io/badge/Version-2.16-brightgreen.svg?style=flat-square)](#versions)
[![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/)
[![Foo](https://img.shields.io/badge/%E2%82%BD$%E2%82%AC%20%D0%9D%D0%B0%20%D0%BF%D0%B8%D0%B2%D0%BE-%D1%81%20%D1%80%D1%8B%D0%B1%D0%BA%D0%BE%D0%B9-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/)
@@ -66,6 +66,7 @@ ESP8266 (SDK v2.6+), ESP32
- [Время получения сообщения](#time)
- [Часы реального времени](#rtc)
- [Обновление прошивки из чата](#ota)
+ - [Оформление текста](#textmode)
- [Всякие трюки](#tricks)
- [Версии](#versions)
- [Баги и обратная связь](#feedback)
@@ -344,6 +345,7 @@ bot.sendMessage("Hello!", "112233"); // уйдёт в "112233"
- `bool isBot` - сообщение от бота
- `bool OTA` - запрос на OTA обновление (получен .bin файл)
- `uint32_t unix` - время сообщения
+ - `String fileName` - имя файла
- `String toString()` - вся информация из сообщения, удобно для отладки (с версии 2.11)
**Примечания:**
@@ -559,6 +561,23 @@ if (msg.OTA && msg.text == "update") bot.update();
if (msg.OTA && msg.chatID == "123456") bot.update();
```
+
+## Оформление текста
+Библиотека поддерживает оформление текста в сообщениях. Разметка оформления выбирается при помощи `setTextMode(mode)`, где `mode`:
+- `FB_TEXT` - по умолчанию (оформление отключено)
+- `FB_MARKDOWN` - разметка Markdown v2
+- `FB_HTML` - разметка HTML
+
+Доступные теги описаны в [API Telegram](https://core.telegram.org/bots/api#formatting-options). Например для Markdown:
+```cpp
+bot.setTextMode(FB_MARKDOWN);
+bot.sendMessage(F("*Bold*, ~Strike~, `code`, [alexgyver.ru](https://alexgyver.ru/)"));
+```
+
+Выведет в чат: **Bold**, ~~Strike~~, `code`, [alexgyver.ru](https://alexgyver.ru/)
+
+> **Внимание!** В режиме FB_MARKDOWN нельзя использовать в сообщениях символы `! + #`, сообщение не отправится. Возможно получится исправить в будущем (проблема urlencode и экранирования зарезервированных символов).
+
## Трюки
@@ -645,6 +664,7 @@ void loop() {
- v2.13: Оптимизация памяти. Добавил OTA обновление
- v2.14: Улучшен парсинг строки с ID, добавил отключение OTA, добавил парсинг названия группы/канала в username
- v2.15: Заплатка для кривой библиотеки ESP32
+- v2.16: добавлен вывод fileName, пофикшены неотправляемые сообщения в Markdown режиме
## Баги и обратная связь
diff --git a/examples/textMode/textMode.ino b/examples/textMode/textMode.ino
index 35ac318..cdec0fe 100644
--- a/examples/textMode/textMode.ino
+++ b/examples/textMode/textMode.ino
@@ -12,33 +12,11 @@ void setup() {
connectWiFi();
bot.setChatID(CHAT_ID);
- bot.setTextMode(FB_MARKDOWN);
+ bot.setTextMode(FB_MARKDOWN); // вернуть по умолчанию - FB_TEXT
// по форматированию читай тут https://core.telegram.org/bots/api#formatting-options
- // символ точка . нужно экранировать как \\.
- bot.sendMessage(F("*Bold*, ||spoiler||, ~Strike~, `code`, [alexgyver\\.ru](https://alexgyver\\.ru/)"));
-
- // пример из доки
- // https://core.telegram.org/bots/update56kabdkb12ibuisabdubodbasbdaosd
- bot.sendMessage(F("*bold _italic bold ~italic bold strikethrough ||italic bold strikethrough spoiler||~ __underline italic bold___ bold*"));
+ bot.sendMessage(F("*Bold*, ||spoiler||, ~Strike~, `code`, [alexgyver.ru](https://alexgyver.ru/)"));
}
-/*
- bold \*text
- _italic \*text_
- __underline__
- ~strikethrough~
- ||spoiler||
- [inline URL](http://www.example.com/)
- [inline mention of a user](tg://user?id=123456789)
- `inline fixed-width code`
- ```
- pre-formatted fixed-width code block
- ```
- ```python
- pre-formatted fixed-width code block written in the Python programming language
- ```
-*/
-
void loop() {
bot.tick();
}
diff --git a/keywords.txt b/keywords.txt
index cb1e035..805746e 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -70,6 +70,7 @@ edited KEYWORD2
isBot KEYWORD2
OTA KEYWORD2
unix KEYWORD2
+fileName KEYWORD2
toString KEYWORD2
second KEYWORD2
diff --git a/library.properties b/library.properties
index b1b07cc..069751f 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=FastBot
-version=2.15
+version=2.16
author=AlexGyver
maintainer=AlexGyver
sentence=Simple library for Telegram bot (messages and menus)
diff --git a/src/FastBot.h b/src/FastBot.h
index cb2da84..7235518 100644
--- a/src/FastBot.h
+++ b/src/FastBot.h
@@ -81,6 +81,7 @@
v2.13: Оптимизация памяти. Добавил OTA обновление
v2.14: Улучшен парсинг строки с ID, добавил отключение OTA, добавил парсинг названия группы/канала в username
v2.15: Заплатка для кривой библиотеки ESP32
+ v2.16: добавлен вывод fileName, пофикшены неотправляемые сообщения в Markdown режиме
*/
/*
@@ -327,6 +328,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String umsg;
FB_urlencode(msg, umsg);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(umsg);
#endif
String req;
_addToken(req);
@@ -368,6 +370,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String utext;
FB_urlencode(text, utext);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(utext);
#endif
String req;
_addToken(req);
@@ -428,6 +431,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String utext;
FB_urlencode(text, utext);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(utext);
#endif
String req;
_addToken(req);
@@ -554,6 +558,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String umsg;
FB_urlencode(msg, umsg);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(umsg);
#endif
String req;
_addToken(req);
@@ -594,6 +599,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String umsg;
FB_urlencode(msg, umsg);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(umsg);
#endif
String req;
_addToken(req);
@@ -626,6 +632,7 @@ class FastBot {
#ifndef FB_NO_URLENCODE
String umsg;
FB_urlencode(msg, umsg);
+ if (parseMode == FB_MARKDOWN) FB_escMarkdown(umsg);
#endif
String req;
_addToken(req);
@@ -857,8 +864,10 @@ class FastBot {
#ifndef FB_NO_OTA
String file;
+ String fileName;
if (_file_ptr) _file_ptr = nullptr;
if (find(str, file, textPos, F("\"file_name\":\""), '\"', IDpos)) {
+ fileName = file;
if (file.endsWith(F(".bin"))) {
find(str, file, textPos, F("\"file_id\":\""), '\"', IDpos);
_file_ptr = &file;
@@ -900,6 +909,7 @@ class FastBot {
is_bot[0] == 't',
(bool)_file_ptr,
(uint32_t)date.toInt(),
+ fileName,
// legacy
userID,
diff --git a/src/datatypes.h b/src/datatypes.h
index a1b3143..de6770e 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -13,6 +13,7 @@ struct FB_msg {
bool isBot; // сообщение от бота
bool OTA; // запрос на OTA обновление
uint32_t unix; // время сообщения
+ String& fileName; // имя файла
// legacy
String& usrID; // ID юзера
diff --git a/src/utils.cpp b/src/utils.cpp
index 12b7acb..c2ddded 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -1,5 +1,32 @@
#include "utils.h"
+void FB_escHTML(String& s) {
+ String out;
+ out.reserve(s.length());
+ for (uint16_t i = 0; i < s.length(); i++) {
+ switch (s[i]) {
+ case '<': out += F("<"); break;
+ case '>': out += F(">"); break;
+ case '&': out += F("&"); break;
+ default: out += s[i]; break;
+ }
+ }
+ s = out;
+}
+
+static const char FB_escList[] = ">-={}.!";
+
+void FB_escMarkdown(String& s) {
+ String out;
+ out.reserve(s.length());
+ for (uint16_t i = 0; i < s.length(); i++) {
+ if (strchr(FB_escList, s[i]) != 0) out += '\\';
+ out += s[i];
+ }
+ Serial.println(out);
+ s = out;
+}
+
int64_t FB_str64(const String &s) {
return atoll(s.c_str());
}
@@ -8,10 +35,10 @@ String FB_64str(int64_t id) {
int32_t s1 = (int64_t)id % 1000000000;
int32_t s2 = (int64_t)id / 1000000000;
if (s2) {
- s += s2;
- s += abs(s1);
+ s += s2;
+ s += abs(s1);
} else {
- s += s1;
+ s += s1;
}
return s;
}
@@ -74,7 +101,7 @@ void FB_unicode(String &uStr) {
out += (char)(0b10000000 | (uBytes & 0b111111));
}
break;
- default: out += uStr[i]; break;
+ default: out += uStr[i]; break;
}
}
}
diff --git a/src/utils.h b/src/utils.h
index 7cdc289..af958b4 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -2,30 +2,32 @@
#include
void FB_unicode(String &uStr);
void FB_urlencode(const String& s, String& dest);
+void FB_escHTML(String& s);
+void FB_escMarkdown(String& s);
int64_t FB_str64(const String &s);
String FB_64str(int64_t id);
struct FB_Parser {
FB_Parser() {
- str.reserve(20);
+ str.reserve(20);
}
bool parseNT(const String& s) {
- while (!end) {
- char c1 = s[++i];
- if (c1 == '\t' || c1 == '\n' || c1 == '\0') {
- int to = i;
- if (s[to - 1] == ' ') to--;
- if (s[from] == ' ') from++;
- str = s.substring(from, to);
- from = i + 1;
- end = (c1 == '\0');
- div = c1;
- return 1;
+ while (!end) {
+ char c1 = s[++i];
+ if (c1 == '\t' || c1 == '\n' || c1 == '\0') {
+ int to = i;
+ if (s[to - 1] == ' ') to--;
+ if (s[from] == ' ') from++;
+ str = s.substring(from, to);
+ from = i + 1;
+ end = (c1 == '\0');
+ div = c1;
+ return 1;
+ }
}
- }
- return 0;
+ return 0;
}
bool parse(const String& s) {