Один из вопросов, который часто приходит в личку — как работать со смайлами(эмодзи) и стикерами.
Как с ними работать, какими инструментами пользуюсь я и т.д.
В данной части будут рассмотрены такие вещи: как создать сообщение со стикером, как обработать полученное сообщение со стикером, как найти в тексте сообщения все смайлы(эмодзи), как создать сообщение с использованием смайлов (эмодзи).
Кому интересно, прошу под кат.
По-традиции, начинаем статью со ссылки на исходники по ней :)
Весь обсуждаемый в статье код собран в ветке Part3-Stick_and_Emoji.
Одна из вещей, что мне так понравилась в телеграмме, как только он появился — были стикеры. Они классные, удобные, бесплатные. И все это огромное разнообразие стикеров нам, естественно, хочется использовать и в боте. На деле эта процедура очень простая. Чтобы отправить стикер пользователю, нам нужно знать только лишь id стикера и больше ничего.
Обычно для стикеров я создаю себе вот такой класс-помощник, где храню данные о используемых в боте стикерах:
Stickers.java
Тут все просто. Мы даем стикеру имя, понятное для нас. И с помощью пары методов получаем готовые объект для отправки пользователю.
Для того, чтобы ответить на вопрос: «Где взять ID стикера?», — давайте напишем себе помощника, который эти данные нам и будет сообщать в нашем же боте.
У нас есть базовый функционал, который мы создавали тут:
TelegramBot. Базовый функционал. (Часть 2)
Чтобы наш бот начал как-то обрабатывать принятые стикеры, нам нужно:
Задача : при получении стикера в чат, бот должен в ответ прислать текстовое сообщение с ID стикера.
В список команд мы добавили команду STICKER
В анализаторе присланного апдейта мы попробуем определить, текстовое ли у нас сообщение или в нем содержится стикер:
MessageReciever.java строка 57
Т.к. сложной обработки присланного сообщения нам делать не нужно, то обработку сообщений, содержащих стикер, мы поручим уже существующему хендлеру, ответственному за обаботку так называемых «системных сообщений»:
MessageReciever.java строка 86
Соответственно в SystemHandler нам нужно указать, как обрабатывать поступившую команду STICKER:
SystemHandler.java строка 31
В результате, при отправке нашему боту любой стикер — мы получим в ответ его ID:
Они стандартизировались, почти все устройства и операционные системы их понимают и умеют отображать. Их очень удобно использовать для украшения сообщений. Они лаконично смотрятся на кнопках под сообщениями. Как ни крути — одни плюсы.
Например в боте-планировщике событий
Используя одинаковые иконки на кнопках и в тексте сообщения вы позволяете пользователю интуитивно и разобраться в вашем интерфейсе, на загромождая сообщение и кнопки лишним текстом.
Чтобы отобразить эмодзи в сообщении или на кнопке вам нужно знать его Unicode. В интернете полно источников, где можно найти все перечисленные смайлики, где указаны их теги, коды.
Для себя я выбрал такой способ работы с эмодзи: удобнее смайлы смотреть и выбирать в самом телеграмме.
Ну и естественно, по-аналогии со стикерами, давайте напишем себе небольшого помощника, который нам будет показывать нужные коды да еще и так, чтобы мы гарантированно правильно могли их обработать.
В первую очередь добавим в pom.xml вот такую зависимость:
Честно, уже не помню, где она мне попалась, но с тех пор пользуюсь только ей, если мне нужно что-то сделать со смайликами в моем боте.
В библиотеке собрано много разных инструментов:
Любознательным и пытливым будет где развернуться :)
Что же нужно, чтобы отправить смайлик с помощью бота? Нужно встроить в текст сообщения Unicode нужного эмодзи.
Да, можно найти ресурсы, которые дают списки юникодов с эмодзи, показывают разные сводные таблицы как выглядят смайлы на разных смартфонах.
Я же хочу вам показать способ, который для меня оказался самым удобным для работы со смайлами.
Сначала рассмотрим как же можно использовать смайлы в самом телеграмме. Вы можете вызвать диалоговое окно, где все смайлы перечислены и добавлять их в сообщение, просто нажимая на их иконки. Так же смайлики можно добавлять в сообщение с помощью тэгов.
Тэги должны быть обрамлены в двоеточние и содержать какой-то уникальный текст, обозначающий нужный смайл.
Если в поле для ввода сообщения начать вводить сообщение, начинающееся с двоеточия — телеграм сам начнет показывать, какие эмодзи содержат вводимый текст тэга:
И когда вы введете правильный тэг смайла и поставите еще одно двоеточие — текст превратится в смайл. Так же тэги отображаются, если на смайлике зажать левую кнопку мыши.
И вот теперь нам на помощь приходит библиотека, зависимость которой мы добавили выше. Она умеет работать с тэгами смайликов. Это удобно в первую очередь для вас, так как теги более читаемы, они несут какой-то смысл.
А мы, зная тэг, можем получить Unicode смайлика вот таким образом:
Вы можно завести себе отдельный класс, в котором будете хранить смайлы, которые используете в боте. На примере того же планировщика событий, у него в арсенале вот такие смайлы:
И вот так в коде будет выглядеть использование этого класса и конкретного смайлика:
Это код вот этой кнопки:
Я заметил один нюанс этой библиотеки. Не все смайлы, что есть в телеграмме, библиотека умеет распознавать. Поэтому следите за тем, как выходят новые версии библиотеки.
Ну а чтобы быть точно уверенным, какие смайлы мы можем показать, а какие нет — эту задачу мы и поручим решать нашему помощнику.
Задача: если присланное сообщение не содержит никакой конкретной команды, но содержит в тексте смайлы — вывести эти смайлы на экран пользователю в виде сообщения и указать их аттрибуты(тег и описание).
Добавим в список команд команду TEXT_CONTAIN_EMOJI
Command.java строка 8
В парсере, который определяет, что за команда содержится в нашем сообщении добавим вот такой текст:
Parser.java строка 38
Если мы определили, что сообщение не содержит никакой конкретной команды, но в нем есть смайлы — мы возвращаем, что мы отпарсили команду TEXT_CONTAIN_EMOJI.
Создадим отдельный хендлер, который будет обрабатывать только эту команду:
EmojiHandler.java
Данный код выделяет из текста сообщения только смайлики, формирует из них сет с уникальными выбирает из их свойств теги и описание и формирует из этого текстовое сообщение.
Результат работы выглядит вот так:
В квадратных скобках мы получаем теги, которые можем использовать для вставки смайликов. Можно увидеть, что к одному смайлику иногда относится более чем 1 тег.
И так же с помощью данного помощника мы можем точно понять, какие смайлики понимает наша библиотека, а какие игнорирует.
Как, например, видно тут:
Смайл с кодом :face_with_monocle: почему-то не детектируется этой библиотекой.
Итак, обработчик у нас есть. Как мы передадим ему задание?
Т.к. мы уже знаем, что текстовое сообщение со смайликами внутри детектируется как команда TEXT_CONTAIN_EMOJI — в MessageReciever нам нужно указать, что за обработку этой команды ответственен отдельный хендлер EmojiHandler.
MessageReciever.java строка 94
Программируйте в удовольствие и не стейсняйтесь задавать вопросы :)
P.S.
Бота с этим функционалом вы можете пощупать вот тут: https://t.me/test_habr_bot.
Как с ними работать, какими инструментами пользуюсь я и т.д.
В данной части будут рассмотрены такие вещи: как создать сообщение со стикером, как обработать полученное сообщение со стикером, как найти в тексте сообщения все смайлы(эмодзи), как создать сообщение с использованием смайлов (эмодзи).
Кому интересно, прошу под кат.
По-традиции, начинаем статью со ссылки на исходники по ней :)
Весь обсуждаемый в статье код собран в ветке Part3-Stick_and_Emoji.
Стикеры
Одна из вещей, что мне так понравилась в телеграмме, как только он появился — были стикеры. Они классные, удобные, бесплатные. И все это огромное разнообразие стикеров нам, естественно, хочется использовать и в боте. На деле эта процедура очень простая. Чтобы отправить стикер пользователю, нам нужно знать только лишь id стикера и больше ничего.
Обычно для стикеров я создаю себе вот такой класс-помощник, где храню данные о используемых в боте стикерах:
Stickers.java
import org.telegram.telegrambots.api.methods.send.SendSticker;
public enum Stickers {
FUNNY_JIM_CARREY("CAADBQADiQMAAukKyAPZH7wCI2BwFxYE"),
;
String stickerId;
Stickers(String stickerId) {
this.stickerId = stickerId;
}
public SendSticker getSendSticker(String chatId) {
if ("".equals(chatId)) throw new IllegalArgumentException("ChatId cant be null");
SendSticker sendSticker = getSendSticker();
sendSticker.setChatId(chatId);
return sendSticker;
}
public SendSticker getSendSticker() {
SendSticker sendSticker = new SendSticker();
sendSticker.setSticker(stickerId);
return sendSticker;
}
}
Тут все просто. Мы даем стикеру имя, понятное для нас. И с помощью пары методов получаем готовые объект для отправки пользователю.
Для того, чтобы ответить на вопрос: «Где взять ID стикера?», — давайте напишем себе помощника, который эти данные нам и будет сообщать в нашем же боте.
У нас есть базовый функционал, который мы создавали тут:
TelegramBot. Базовый функционал. (Часть 2)
Чтобы наш бот начал как-то обрабатывать принятые стикеры, нам нужно:
- Определить, что нам прислали стикер
- Указать, какой именно хендлер ответственнен за обработку сообщений со стикерами
- Запустить хендлер, который сформирует сообщение пользователю в ответ
Задача : при получении стикера в чат, бот должен в ответ прислать текстовое сообщение с ID стикера.
В список команд мы добавили команду STICKER
В анализаторе присланного апдейта мы попробуем определить, текстовое ли у нас сообщение или в нем содержится стикер:
MessageReciever.java строка 57
if (message.hasText()) {
parsedCommand = parser.getParsedCommand(message.getText());
} else {
Sticker sticker = message.getSticker();
if (sticker != null) {
parsedCommand = new ParsedCommand(Command.STICKER, sticker.getFileId());
}
}
Т.к. сложной обработки присланного сообщения нам делать не нужно, то обработку сообщений, содержащих стикер, мы поручим уже существующему хендлеру, ответственному за обаботку так называемых «системных сообщений»:
MessageReciever.java строка 86
case START:
case HELP:
case ID:
case STICKER:
SystemHandler systemHandler = new SystemHandler(bot);
log.info("Handler for command[" + command.toString() + "] is: " + systemHandler);
return systemHandler;
Соответственно в SystemHandler нам нужно указать, как обрабатывать поступившую команду STICKER:
SystemHandler.java строка 31
case STICKER:
return "StickerID: " + parsedCommand.getText();
В результате, при отправке нашему боту любой стикер — мы получим в ответ его ID:
Смайлы или эмодзи
Они стандартизировались, почти все устройства и операционные системы их понимают и умеют отображать. Их очень удобно использовать для украшения сообщений. Они лаконично смотрятся на кнопках под сообщениями. Как ни крути — одни плюсы.
Например в боте-планировщике событий
Используя одинаковые иконки на кнопках и в тексте сообщения вы позволяете пользователю интуитивно и разобраться в вашем интерфейсе, на загромождая сообщение и кнопки лишним текстом.
Чтобы отобразить эмодзи в сообщении или на кнопке вам нужно знать его Unicode. В интернете полно источников, где можно найти все перечисленные смайлики, где указаны их теги, коды.
Для себя я выбрал такой способ работы с эмодзи: удобнее смайлы смотреть и выбирать в самом телеграмме.
Ну и естественно, по-аналогии со стикерами, давайте напишем себе небольшого помощника, который нам будет показывать нужные коды да еще и так, чтобы мы гарантированно правильно могли их обработать.
В первую очередь добавим в pom.xml вот такую зависимость:
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>3.3.0</version>
</dependency>
Честно, уже не помню, где она мне попалась, но с тех пор пользуюсь только ей, если мне нужно что-то сделать со смайликами в моем боте.
В библиотеке собрано много разных инструментов:
Любознательным и пытливым будет где развернуться :)
Что же нужно, чтобы отправить смайлик с помощью бота? Нужно встроить в текст сообщения Unicode нужного эмодзи.
Да, можно найти ресурсы, которые дают списки юникодов с эмодзи, показывают разные сводные таблицы как выглядят смайлы на разных смартфонах.
Я же хочу вам показать способ, который для меня оказался самым удобным для работы со смайлами.
Сначала рассмотрим как же можно использовать смайлы в самом телеграмме. Вы можете вызвать диалоговое окно, где все смайлы перечислены и добавлять их в сообщение, просто нажимая на их иконки. Так же смайлики можно добавлять в сообщение с помощью тэгов.
Тэги должны быть обрамлены в двоеточние и содержать какой-то уникальный текст, обозначающий нужный смайл.
Если в поле для ввода сообщения начать вводить сообщение, начинающееся с двоеточия — телеграм сам начнет показывать, какие эмодзи содержат вводимый текст тэга:
И когда вы введете правильный тэг смайла и поставите еще одно двоеточие — текст превратится в смайл. Так же тэги отображаются, если на смайлике зажать левую кнопку мыши.
И вот теперь нам на помощь приходит библиотека, зависимость которой мы добавили выше. Она умеет работать с тэгами смайликов. Это удобно в первую очередь для вас, так как теги более читаемы, они несут какой-то смысл.
А мы, зная тэг, можем получить Unicode смайлика вот таким образом:
String emoji_kissing = EmojiParser.parseToUnicode(":kissing:");
Вы можно завести себе отдельный класс, в котором будете хранить смайлы, которые используете в боте. На примере того же планировщика событий, у него в арсенале вот такие смайлы:
import com.vdurmont.emoji.EmojiParser;
public enum Icon {
PLUS(":heavy_plus_sign:"),
MINUS(":heavy_minus_sign:"),
CHECK(":white_check_mark:"),
NOT(":x:"),
DOUBT(":zzz:"),
FLAG(":checkered_flag:")
private String value;
public String get() {
return EmojiParser.parseToUnicode(value);
}
Icon(String value) {
this.value = value;
}
}
И вот так в коде будет выглядеть использование этого класса и конкретного смайлика:
row.add(new InlineKeyboardButton()
.setText(Icon.CHECK.get() + " I'm going")
Это код вот этой кнопки:
Я заметил один нюанс этой библиотеки. Не все смайлы, что есть в телеграмме, библиотека умеет распознавать. Поэтому следите за тем, как выходят новые версии библиотеки.
Ну а чтобы быть точно уверенным, какие смайлы мы можем показать, а какие нет — эту задачу мы и поручим решать нашему помощнику.
Задача: если присланное сообщение не содержит никакой конкретной команды, но содержит в тексте смайлы — вывести эти смайлы на экран пользователю в виде сообщения и указать их аттрибуты(тег и описание).
Добавим в список команд команду TEXT_CONTAIN_EMOJI
Command.java строка 8
public enum Command {
...
TEXT_CONTAIN_EMOJI,
...
}
В парсере, который определяет, что за команда содержится в нашем сообщении добавим вот такой текст:
Parser.java строка 38
if (result.getCommand() == Command.NONE) {
List<String> emojiContainsInText = EmojiParser.extractEmojis(result.getText());
if (emojiContainsInText.size() > 0) result.setCommand(Command.TEXT_CONTAIN_EMOJI);
}
Если мы определили, что сообщение не содержит никакой конкретной команды, но в нем есть смайлы — мы возвращаем, что мы отпарсили команду TEXT_CONTAIN_EMOJI.
Создадим отдельный хендлер, который будет обрабатывать только эту команду:
EmojiHandler.java
import com.example.telegrambot.bot.Bot;
import com.example.telegrambot.command.ParsedCommand;
import com.vdurmont.emoji.Emoji;
import com.vdurmont.emoji.EmojiManager;
import com.vdurmont.emoji.EmojiParser;
import org.apache.log4j.Logger;
import org.telegram.telegrambots.api.objects.Update;
import java.util.HashSet;
import java.util.Set;
public class EmojiHandler extends AbstractHandler {
private static final Logger log = Logger.getLogger(EmojiHandler.class);
public EmojiHandler(Bot bot) {
super(bot);
}
@Override
public String operate(String chatId, ParsedCommand parsedCommand, Update update) {
String text = parsedCommand.getText();
StringBuilder result = new StringBuilder();
Set<String> emojisInTextUnique = new HashSet<>(EmojiParser.extractEmojis(text));
if (emojisInTextUnique.size() > 0) result.append("Parsed emojies from message:").append("\n");
for (String emojiUnicode : emojisInTextUnique) {
Emoji byUnicode = EmojiManager.getByUnicode(emojiUnicode);
log.debug(byUnicode.toString());
String emoji = byUnicode.getUnicode() + " " +
byUnicode.getAliases() +
" " + byUnicode.getDescription();
result.append(emoji).append("\n");
}
return result.toString();
}
}
Данный код выделяет из текста сообщения только смайлики, формирует из них сет с уникальными выбирает из их свойств теги и описание и формирует из этого текстовое сообщение.
Результат работы выглядит вот так:
В квадратных скобках мы получаем теги, которые можем использовать для вставки смайликов. Можно увидеть, что к одному смайлику иногда относится более чем 1 тег.
И так же с помощью данного помощника мы можем точно понять, какие смайлики понимает наша библиотека, а какие игнорирует.
Как, например, видно тут:
Смайл с кодом :face_with_monocle: почему-то не детектируется этой библиотекой.
Итак, обработчик у нас есть. Как мы передадим ему задание?
Т.к. мы уже знаем, что текстовое сообщение со смайликами внутри детектируется как команда TEXT_CONTAIN_EMOJI — в MessageReciever нам нужно указать, что за обработку этой команды ответственен отдельный хендлер EmojiHandler.
MessageReciever.java строка 94
case TEXT_CONTAIN_EMOJI:
EmojiHandler emojiHandler = new EmojiHandler(bot);
log.info("Handler for command[" + command.toString() + "] is: " + emojiHandler);
return emojiHandler;
Программируйте в удовольствие и не стейсняйтесь задавать вопросы :)
P.S.
Бота с этим функционалом вы можете пощупать вот тут: https://t.me/test_habr_bot.
decomeron
Спасибо