Задать вопрос
  • Как получить доступ к данным, отправленным через URL с помощью метода POST(Python)?

    shurshur
    @shurshur
    Евгений, я его прочитал. Вижу вопрос как сделать POST-запрос. Это есть в документации. В частности, в документации к популярным библиотекам requests и aiohttp.
  • Что ему не нравится с моим буффером?

    shurshur
    @shurshur
    Что должна делать эта программа?
  • Есть ли годный браузер с поддержкой Flash?

    shurshur
    @shurshur
    Есть ли годный гроб для мёртвой стюардессы?
  • Как вспомнить\восстановить пароль Veracrypt?

    shurshur
    @shurshur
    rav_pr, люди легко забывают пароль, придуманный всего пять минут назад, а тут год прошёл...
  • Как добавлять пользователя в телеграмм канал по номеру телефона?

    shurshur
    @shurshur
    В общем случае - никак. У многих юзеров стоит в настройках приватности запрет на их поиск по номеру телефона.

    Кроме того, Телеграм банит за активный поиск пользователей по номеру телефона.
  • Как добавить чат боту webhook?

    shurshur
    @shurshur
    Можно взять flask и с его помощью написать тривиальный сервис.
  • Как остановить handler?

    shurshur
    @shurshur
    xx_RuBiCoN_xx,
    telebot (как и вообще большинство библиотек для написания чат-ботов) работает как обработчик поступающих событий. Приходит событие - вызывается его обработчик. И это очень хорошо работает, пока всё осмысленное взаимодействие с ботом локализовано одним сообщением, а предыдущие знать вообще не обязательно. Ну, например, бот-переводчик: мы кидаем ему фразу на одном языке, он вовзращает на другом языке.

    Когда же поведение при обработке конкретного сообщения начинает находиться в зависимости от предыстории, то уже не так просто. Нужно для каждого пользователя (точнее, каждого chat_id) помнить некое состояние, которое определяет поведение на текущем шаге.

    На самом деле хранить состояния своими силами тоже можно, и я бы посоветовал в учебных целях хотя бы один раз это попробовать. Заводим глобальную переменную-словарь user_statses = dict(), куда будем записывать состояния пользователей.

    user_state = user_states.get(message.chat.id, None)
    if user_state:
        if user_state["action"] = "button1": функция_обработчик_кнопки1(message)
        elif user_state["action"] = "button2": функция_обработчик_кнопк2(message)
        else: функция_которая_покажет_ошибку(message)
    else:
        поведение по умолчанию, например, обработка нажатых кнопок
        в нужном месте выставляем состояние:
        user_state[message.chat.id] = {"action": "button1", "дополнительные": "данные"}


    Тогда можно добиться того, чтобы вместо поведения по умолчанию выполнялся другой код.

    В состояние можно даже класть ссылку на функцию, которая будет вызвана:

    user_state[message.chat.id]["func"] = функция_обработки_сообщения
    #или даже так:
    user_state[message.chat.id]["func"] = lambda msg: функция_обработки_сообщения(msg, "дополнительные", "параметры")


    Тогда в нужном месте можно вызвать эту функцию:

    if "func" in user_states.get(message.chat.id, {}):
        user_states[message.chat.id]["func"](message)


    Но при таком подходе код может выглядеть достаточно громоздко. Поэтому библиотеки предлагают различные способы оптимизировать этот процесс. Вот telebot, например, позволяет использовать register_next_step_handler, который в какой-то свой внутренний словарь сохраняет следующую вызываемую функцию, примерно так же, как приведённом выше примере. Выбор обработчика при обработке очередного сообщения также делает библиотека, поэтому нам его писать не нужно.

    Так что любой многошаговый бот просто содержит в каждом обработчике вызов register_next_step_handler, который приводит к изменению обработчика следующего сообщения от этого пользователя. Можно даже с ветвлениями: в зависимости от условий можно зарегистрировать в одной функции разные обработчики.

    Если же надо, чтобы бот вернулся "в главное меню" (на самый первый обработчик), то делаем clear.
  • Как остановить handler?

    shurshur
    @shurshur
    xx_RuBiCoN_xx, ну вот в handle_number_input надо сделать clear. И в handle_number_input2 надо сделать clear. После того, как операция сделана, нужно сброситься до изначального состояния. Чтобы сделующее действие не вызывало handle_number_input или handle_number_input2, а вызывало основной обработчик.

    А вообще, конечно, названия типа handle_number_input2 это плохо. Должно быть сразу понятно, что это обработчик, который удаляет. Типа handle_number_delete_from_table.

    Ну а вообще код привести бы в приличное состояние. Сам подумай: через год ты вдруг захочешь поменять что-то в боте, и сколько ты будешь разбираться в глубоком смысле таких конструкций?

    elif message.text == text42:
            handle_adm_btn1(bot, message)
  • Как остановить handler?

    shurshur
    @shurshur
    xx_RuBiCoN_xx, не надо сразу, надо в следующем обработчике.
  • Как остановить handler?

    shurshur
    @shurshur
    xx_RuBiCoN_xx, да, вечно вместо clear_ вспоминаю cancel_.

    Не должно быть никаких "методом проб и ошибок". Надо чётко понимать, что делает код.

    Принцип очень простой. В обычном обработчике вешаем следующий (register_next_step_handler) и дальше по цепочке следующие. Как только надо "выкинуть в главное меню", делаем clear_step_handler (в теории можно было бы сделать register_next_step_handler на самый главный обработчик, но это не очень хорошо, так как при clear освобождается занятая под состояние память, а тут нет).
  • Как остановить handler?

    shurshur
    @shurshur
    bot.cancel_step_handler(message)

    или:

    bot.cancel_step_handler_by_chat_id(message.chat.id)
  • Как вывести ключи из json в столбце?

    shurshur
    @shurshur
    Это вопрос на знание элементарных основ.
  • Существует ли инструмент для управления серверами ssh?

    shurshur
    @shurshur
    ansible же, у него есть таски и для создания/изменения юзеров и групп, и тас authorized_keys позволяет ключ положить...

    Но возможно вам правильнее уже будет внедрить ldap/freeipa/итп, как ниже пишут.
  • Возможно ли использовать esp32+nrf24l01 в качестве репитера для передачи wi fi сигнала с эхолота?

    shurshur
    @shurshur
    Filipp Filippovich, 200-300 Wi-Fi берёт только с направленной антенной и скорее всего не самым убогим радиомодулем, а в этих мелких устройствах всё сделано для минимизации цены, размеров и энергопотребления. Так что скорее всего не очень это идея.
  • Как самому провалидировать сертификат x509?

    shurshur
    @shurshur
    Читать man по openssl verify. Там, грубо, передаёшь сертификат и подписавший его сертификат, и он говорит ок или не ок. Просто прогоняешь от корневого до конечного всю цепочку так...
  • Как интегрировать Whatsapp на сайт?

    shurshur
    @shurshur
    modcode, легальный API - да, платный. Зато всё белое и пушистое и с обязательствами, уже есть интеграции и в bitrix, и в jivosite, и в различных CRM/чатцентрах/чатботах. Чтобы сэкономить, народ рискует, играется нелегально с API для web.whatsapp.com, формально это запрещено, в реальности если не спамить и объёмы маленькие, то риски бана невелики. Но всё равно Особо Важный Номер в такой интеграции я бы не рекомендовал использовать. Лучше такой, что не страшно поменять.
  • Какие можно использовать технологии/форматы для хранения бинарных пользовательских данных в десктопном приложении?

    shurshur
    @shurshur
    Вообще-то файловая система - наиболее эффективное хранилище для таких задач.

    1. Легко масштабируется, бэкапится.
    2. Эффективно кэшируется операционной системой.
    3. Множественный конкурентный доступ к разным файлам этой большой базы без каких-либо спецэффектов.
    4. Риск повреждения данных минимальный. Разве что повреждается тот файл, который не успел записаться в момент ёк-ёк.

    Архив это плохо - он по сути на каждую операцию изменения файла пересоздаётся заново. И если что - весь архив отлетает со всеми данными.

    Минио на каждый файл создаёт каталог, внутри которого файл (возможно, зашифрованный) и json с метаданными - тут объектов файловой системы ещё больше, чем при обычном хранении файлов.

    Виртуальный диск - это прям из пушки по воробъям. Проще и даже надёжнее тогда хранить файлы в sqlite, которая, к слову, может иметь формальный размер до 281 Тб (да, именно террабайт). Но база огромного размера это тоже не очень удобно.

    Как правило, нормальная практика - хранить метаданные в sqlite (а может berkeleydb или ещё какой-нить локальной базе), сами файлы - в файлах. Как и написано в том вот ответе внизу. Сами имена файлов могут быть сколь угодно эзотерическими (какие-нить 16-ричные без расширения).

    Иногда делают специфические решения под специфические задачи. Два примера приведу.

    Первый пример - формат mbtiles. Придумали для тайловых данных (TMS) веб-карт, где много тайликов размера 256x256. Представляет из себя sqlite, в котором лежат эти файлы. Для чего используют? Во-первых, для обмена - много софта умеет собирать файлы в такой архивчик. Во-вторых, можно с помощью нарезания на таблицы и создания view оптимизировать хранение тайлов с одинаковым содержанием, что для читающего софта будет прозрачно. Но для приличного продакшн-решения mbtiles напрямую не используют, всё равно раскатывают в файлики.

    Второй пример - программа SAS.Планета. Она позволяет качать в кэш и просматривать такие вот тайлики. Но там возникает проблема хранения миллионов довольно мелких файлов, что прилично напрягает файловую систему. Для оптимизации в ней разработали кастомный формат кэша sqlite, который всё же не одна суперпупербаза, а много 256x256 тайлов собираются в один sqlite-файл, которые уже раскладываются по каталогам. Количество файлов сокращается очень существенно, при этом они не превращаются в одну гигантскую базу с высоким риском повреждения и неудобством каких-либо действий с ней. Например, если мало места и кэш какой-то карты не нужен или не нужны какие-то конкретные масштабные уровни - то легко определить по именам каталогов, что именно удалить.

    Всё это очень специфические случаи и для такого исхитрения есть реальные проблемы и конкретные задачи. А для обычного хранения файлов это чаще всего перебор. Вот надо подумать и решить - действительно ли конкретному десктопному приложению это всё необходимо, или всё же нет?
  • Поставить полного клиента Oracle 19.3 на SUSE Tumbleweed?

    shurshur
    @shurshur
    А зачем вообще ставить из rpm, оно не ставится другими путями, из архива, например?

    В конце концов, можно поставить на el8 (хоть centos, хоть oracle linux) и затем скопировать /opt/oracle (или куда оно там ставится?) на другую машину и даже в другой каталог, указав его в ORACLE_HOME. Если SUSE не слишком исхитряется с общесистемными библиотеками, то должно прокатить (на Ubuntu прокатывает).
  • Как пополнить Steam через Webmoney (API)?

    shurshur
    @shurshur
    Роман Жарков, если это налаженный процесс, то они могут иметь запас на счету в другой платёжной системе и пополнять с него после получения на WM.