Pull to refresh
20
0
Руслан Молчанов @ruslanys

Программист

Send message

Кстати, ребята из Skyeng молодцы! Здорово, что у молодежи есть возможность поработать бок-о-бок с классными, взрослыми специалистами в сильном проекте.


Плюс к карме!)

Интересно, чем остались недовольны люди, задизлайкавшие пост ребенка… Зависть? Глупо.
Ну, вот такой вот onboarding, Жора. Всем нравиться – тоже плохо.


А вообще, искренне желаю успехов! Никого не слушай. Занимайся тем, что тебе по душе и не бойся выгореть или рано разлюбить своё дело! Чушь. Бывает так, что любовь – на всю жизнь.


Эх, где мои 14…
Когда-то и я был похожим школьником: с горящими глазами, полный юношеского максимализма и с миром под ногой.
В то время у нас было меньше возможностей, чем у сегодняшних детей. Не было всяких Ардуин, Интернетов, да и компов домашних. :)
Но точно также, как и вы сегодня, мы тогда с пламенем в глазах делали какой-то очередной сайт, троян или paint.
И тоже было хорошо. Но как здорово, что вам не нужно проходить наш путь. И как здорово, что так много сейчас всего.


Занимайся, развивайся, реализуй свои идеи, проекты, ничего не бойся и ни перед чем не останавливайся! Только вперед!
Бери от своих 14-ти всё! Дальше будет только больше (обязанностей) / меньше (свободного времени): 15, 16, 17, ..., семья, дети, ну ты понял.


Я всю сознательную жизнь в IT, с ранней школы, и не потерял любви. Не понимаю, как это возможно. Мне с возрастом, наоборот, еще больше хочется. Хочется выучить ВСЁ, но уже приходится фильтровать и приоритизировать. А вот тебе нужно реально пробовать всё.


По-доброму завидую отцу. Очень надеюсь, мой сын тоже заинтересуется IT и я смогу делиться с ним всем, что знаю. Смогу отвечать на его вопросы, разбираться вместе с ним и печатать бинго-билетики на термопринтере из скрипта на питоне :) Думаю, папе печать на термопринтере была не меньше интересна, чем Георгию. :)


Успехов!

Обратил внимание на Thread.sleep(). Мне кажется, вместо ConcurrentLinkedQueue в данном конкретном случае лучше взять BlockingQueue и тогда не придется усыплять поток (Thread.sleep). Метод queue.poll() будет его блокировать, а отпускать именно в тот момент, когда появляется сообщение.


А вообще рекомендую глянуть мою статью на эту тему: https://habr.com/ru/post/445072/

Вы правы, но дело в том, что abilities – это не то. Гляньте #Abstraction.


Abilities, условно говоря, это кодогенератор (визард). Он не решает проблем, он упрощает API самой библиотеки, и его функциональность очень примитивна.


Что касается вопроса о велосипеде и TelegramBots, объясню.
Дело в том, что моё и ребят из TelegramBots представления о хорошем коде расходятся. Я не могу такое писать) Я вообще не понимаю, как можно было наплодить моделей с конструктором по умолчанию, игнорируя обязательные поля и пропихивать все через сеттеры, делать это везде и еще писать в доке.
Я бы переписал чуть ли не всё. Но даже если переписывать, то точно на Котлин. А кому это нужно?


Мне кажется, мы с ними концептуально различны. Я смотрю со стороны API разработчика, мне нужен удобный API, пускай и не полностью функциональный (те же inline-клавиатуры), но надежный и решающий проблему. Хотя цель TelegramBots, как раз, как мне кажется, покрыть API Telegram в первую очередь, а потом как-нибудь все прикрутить поудобнее.


Может быть они посмотрят на Telegraff и захотят у себя переделать, и мир станет лучше)


Вместе с тем, я считаю, что концептуально вся библиотека TelegramBots умещается в Telegraff в 3 класса: PollingClient, WebhookClient, TelegramApi.


К тому же Telegraff – это не просто библиотека. Это, скорее, был проект в продакшене, который нужно было перевести на свой DSL. TelegramBots по указаным выше причинам я не хотел использовать, написал для себя и долго еще не мог написать статью, привести в порядок. По этой же причине Telegraff полностью на spring-boot. И по большому счету это легко поправить, но это не приоритетная задача. Конечно, спринг не каждому проекту подходит, но для Телеграм-бота почему бы и нет?


Опять-таки, если кому-то понравилась идея, он хочет пользоваться, внес нужные для себя изменения и оформил в PR – честь и хвала.


Была идея, что если кто-то поддержит донатом проект (но для этого нужно на английский перевести), то эти деньги буду выдавать за PR. Такой фонд. Да и сам готов в этот фонд вкладываться, поэтому пишите код, высылайте PR, отблагодарю)

Ну, смотрите. Как я упоминал, можно сделать Hot Reload этих DSL скриптов без всякой перезагрузки. С другой стороны, не очень понимаю, как можно писать сценарии редакторами в отрыве от программистов, но, в принципе, это возможно и в Telegraff. Сделать, например, в методе process вызов единственного сервисного метода с передачей всех ответов туда и все. Тогда редактора могут делать все, что хотят в скриптах. Им и синтаксис языка знать не нужно.

Чем же вариант с DSL плох? Мне кажется, DSL в принципе для подобного рода задач существует. А так да, это в отдельном файле, посмотрите здесь.

Вы можете написать следующее:


Пример
step<String>("locationFrom") {
    question {
        MarkdownMessage("Откуда поедем?")
    }

    next { "locationTo" }
}

step<String>("locationTo") {
    question {
        MarkdownMessage("Куда поедем?")
    }

    next { "paymentMethod" }
}

Но делать такое поведение платформы по умолчанию было бы избыточно и приводило бы к упомянутому Вами «бойлерплейт».

Приятно отвечать на умные комментарии/вопросы. Спасибо.


Состояние хранится в памяти и при перезапуске оно обнуляется (разумно, наверно, описать это в разделе про особенности). Но на деле, эту задачу также просто решить, как невозможно. С одной стороны, можно хранить текущий обработчик, шаг и ответы в БД, с другой стороны, непонятно как реагировать, если вы (разработчик) изменили ключ шага, например, или тип, или добавили шаг перед. В таком случае персистентное состояние только навредит, а не поможет, потому что не будет консистентно с новой кодовой базой.


Отвечая на ваш вопрос, подумал, что наиболее разумным будет вынести эту конкретную функциональность под интерфейс, вроде StateProvider и отдать на откуп пользователю, добавив в поставку in-memory хранилище по умолчанию. Захотел своё – переопределил bean.

Спасибо за вопрос! Сегодня — нет. Но уже такой запрос был, будет интерес (а вы своим вопросом его проявили), реализую. В принципе, если не заморачиваться и просто прокидывать содержимое сообщения (параметры), то это можно сделать очень быстро.

Я даю платные консультации, могу помочь решить вашу проблему более элегантным методом. В случае заинтересованности, пишите в ЛС.

Т.е. со стороны пользователя отправил сначала /a потом может прилететь /b, /c, /d — как ваш фреймворк предлагает решать подобные кейсы?

На самом деле, не очень понял Вашу проблему. Ну, опишите обработчик под каждую команду, да и все. Пример ниже. Каждую команду можно хранить в отдельном файле. В будущем будет еще и Hot Reload.

Пример
handler("/a") {

    process { _, _ ->
        MarkdownMessage("Привет!")
    }

}
handler("/b") {

    process { _, _ ->
        MarkdownMessage("Привет!")
    }

}



Пожалуйста, прочитайте статью. Остались вопросы – почитайте код github.com/ruslanys/telegraff. То, что вы приводите в качестве аргументов – смешно. Хотите много сценариев, так напишите много. Нелинейными они тоже могут быть. Про Котлин вообще без комментариев.

Признаться, я три дня вложил только, чтобы статью написать, про решение я вообще молчу. Мне – нравится. Указанный Вами TelegramBots я перешел вдоль и поперек, прежде, чем заниматься вот этим всем. Если остались вопросы – это больше не ко мне. От общения конкретно с Вами получаю исключительно негативные эмоции. Еще и карму себе подпортил. Такой вот он, Хабр.

Вам искренне желаю успехов во всех Ваших начинаниях! Надеюсь, на Вашем пути будет больше положительных, чем негативных знакомств!
Чтобы разобраться в том, что такое шаги и фильтры достаточно прочитать эту статью.

Бизнес-логику, как раз, не нужно размазывать. Ваш «контроллер» – это ваш обработчик (сценарий), не нужно бизнес-логику класть внутрь лямбд, возьмите нужный вам сервис из контекста и все.

Повторюсь, TelegramBots это лишь обёртка над Telegram API. Telegraff — фреймворк, навязывающий определённый уровень абстракции для решения этой задачи. Решение может нравиться, а может нет, но сравнивать с TelegramBots это нельзя.

Telegraff – не серебряная пуля и всех проблем не решает. Но каждый имеет право на свое мнение. В любом случае, мне очень жаль, что мне не удалось донести до Вас идею удобства Telegraff.
Сути это не меняет. Признаться, я считаю, и на Java можно это гораздо компактнее написать.

Да какая разница? Ну представьте этот код на Kotlin, что изменится? Суть в том, что TelegramBots просто доставляет вам апдейты от Телеграм и все. Дальше вы уже сами читаете текст, находите нужную команду и т.д. Собственно, блок на Java отражает эти проблемы и суть здесь не в языке. Попробуйте реализовать при таком подходе сценарий с такси из статьи и поймёте разницу. TelegramBots это лишь обёртка над Telegram API. Telegraff — фреймворк, навязывающий определённый уровень абстракции для решения этой задачи. Решение может нравиться, а может нет, но сравнивать с TelegramBots это нельзя.

Это очень похоже на то, как планируется решить вопрос с inline-клавиатурой. Спасибо, хороший пример!

Стремиться, однозначно, есть куда (и думаю, всегда будет). Из ближайшего – inline-клавиатура.

Идея с ключами шагов прекрасна, благодарствую! Попробую что-нибудь такое!
Перечитайте, пожалуйста, статью. Судя по комментарию, Вы совсем не поняли сути. Сравнивать Telegraff и TelegramBots просто бессмысленно. Библиотека, которую Вы указали, не способна решить проблемы, которые решает Telegraff.

В TelegramBots все кончается на получении сообщения из Telegram в метод onUpdateReceived() (это первый раздел этой статьи об устройстве Telegraff). Я уже писал – эта задача тривиальна и на мой взгляд не требует сторонних зависимостей в принципе. Взгляните на пример TelegramBots (WeatherHandlers) и на перечень методов там: `onNewCurrentWeatherCommand`, `onLocationCurrentWeatherCommand`, `onCancelCommand` и т.д. и на то, как они вызываются:

Обработка команд в TelegramBots
private static SendMessage onForecastWeather(Message message, String language) {
    SendMessage sendMessageRequest = null;
    if (message.hasText()) {
        if (message.getText().startsWith(getNewCommand(language))) {
            sendMessageRequest = onNewForecastWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language);
        } else if (message.getText().startsWith(getLocationCommand(language))) {
            sendMessageRequest = onLocationForecastWeatherCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(), language);
        } else if (message.getText().startsWith(getCancelCommand(language))) {
            sendMessageRequest = onCancelCommand(message.getChatId(), message.getFrom().getId(), message.getMessageId(),
                    getMainMenuKeyboard(language), language);
        } else {
            sendMessageRequest = onForecastWeatherCityReceived(message.getChatId(), message.getFrom().getId(), message.getMessageId(),
                    message.getText(), language);
        }
    }
    return sendMessageRequest;
}



Хотите такое писать каждый раз? Я – нет.
Telegraff – дополнительный уровень абстракции над этим всем. Примеры Telegraff здесь.

Уже пора для Kotlin)

1
23 ...

Information

Rating
Does not participate
Location
Минск, Минская обл., Беларусь
Registered
Activity