Задать вопрос
  • Настройка репликации между двумя веб серверами?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Если речь идёт о постоянной синхронизации именно файлов, то очень неплохо работает lsyncd. Только ни в коем случае нельзя пытаться использовать его для синхронизации в две стороны (путём запуска двух экземпляров), только в одну! (Я тестировал, даже если запись идёт только в одну сторону, иногда спонтанно случается синхронизация в неправильную сторону неполностью записанного файла)

    Для баз данных файловую синхронизацию лучше не использовать, для них есть свои методы репликации.

    Разумеется, всё это не отменяет бэкапов и других организационных мер по развёртыванию и поддержке, но можно по возможности максимально снизить риск потери самых последних данных.
    Ответ написан
    3 комментария
  • Телеграм бот на from_user показывает свои данные. Что делать?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    call.message - исходное сообщение, в котором пользователь нажал на кнопку. Разумеется, автором этого сообщения является бот.

    Вместо call.message.from_user надо использовать call.from_user.

    Идея использовать call.message.chat.id для получения id пользователя будет работать только до тех пор, пока это используется в личном чате с пользователем, где chat_id всегда равен user_id. В групповых чатах это работать не будет.
    Ответ написан
    Комментировать
  • Как сделать перенос текса в боте?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Укажи \n или даже \n\n (два переноса - чтобы между абзацами была пустая строка).

    Чтобы использовать html, надо передавать параметр parse_mode='html'. Есть ограничения - не все тэги поддерживаются. См. https://core.telegram.org/bots/api#html-style

    Также есть parse_mode='MarkdownV2' и parse_mode='Markdown, подробнее https://core.telegram.org/bots/api#formatting-options
    Ответ написан
    Комментировать
  • Как пользоваться видимость пакетов Python?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Импорт модуля - это не вставка его кода в вызывающий модуль. Если сделать

    import XXX

    или

    import YYY as XXX

    то в текущей области видимости появится XXX, через который можно будет обращаться к содержимому другого модуля. В частности, можно обращаться к модулям, импортированным в нём:

    import YYY as XXX
    print (XXX.sys.argv)


    Чтобы получить всё, что есть в модуле XXX, в текущей области видимости, можно сделать так:

    from XXX import *

    Но так импортируется реально всё, в том числе модули, которые импортированы в XXX. Но это можно обойти, если внутри XXX в переменной __all__ описать list со всеми именами, которые должны импортироваться при таком импорте. По умолчанию импортируется всё.
    Ответ написан
  • Почему не работает нажатие на inlinekeyboard?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    А как бот узнает, что callback_inline - это обработчик callback query, а не входящего аудиосообщения и не запрос погоды на Марсе? Где у него нужный декоратор?
    Ответ написан
    4 комментария
  • Возможно ли подключить номер к SMPP шлюзу?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    В SMPP вообще никакой привязки к номерам телефонов нет. Можно отправлять и принимать сообщения с какими угодно цифровыми или альфанумерическими подписями.

    Но на деле, конечно, выбирать приходится из того, что разрешают операторы. А операторы для такого случая разрешают одно из двух:

    1. Короткий номер, на который можно принимать сообщения и с которого можно отправлять сообщения. Стоит дорого и надо арендовать у каждого оператора отдельно (заодно уточняя у всех нужных возможность аренды одного и того же номера - он может где-то оказаться уже занят.

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

    В 2021 году СМС - это очень непопулярный сервис. Дорогой и неудобный. Я бы постарался плясать от задачи и поискать способы, по возможности с SMS никак не связанные. Например, если это обращения в поддержку, то их лучше принимать в мессенджерах. Благо сейчас более-менее все популярные позволяют те или иные интеграции.
    Ответ написан
    Комментировать
  • Как написать bash скрипт, который будет запускать файл, который поддерживает аргументы командной строки?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    #!/bin/bash
    python3 get-movies.py "$@"


    Тут запись "$@" означает передать все аргументы скрипта как они есть, причём с правильным экранированием, то есть "Termninator 2" будет передано как "Terminator 2", а не "Terminator" "2".

    upd: Ещё добавлю, что для такого простого случая может больше подойти другой подход: передача интерпретатора через шебанг. Надо первой строкой файла get-movies.py указать:

    #!/usr/bin/env python3

    В этом случае запуск скрипта будет приводить к вызову /usr/bin/env python3 get-movies.py со всеми остальными параметрами.
    Ответ написан
    Комментировать
  • Какие книги существуют для написания, редактирования python-ботов, какие книги порекомендуете новичку?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Марк Лутц. Изучаем Python.

    Собственно, знать используемый язык тут самое важное.
    Ответ написан
    4 комментария
  • Как продолжить принимать сообщения aiogram?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Это плохая идея! Библиотека выбирает первый обработчик, подходящий по условию (в данном случае content_types=["text"]) и остальные не использует вообще.

    Рекомендую либо вставить проверку в каждый handler, либо оформить её как условие в декораторе:

    @dp.message_handler(lambda message: not is_banned(message.from_user.id)


    Можно также написать свой декоратор, чтобы писать просто @check_user_banned. Но это уже по желанию.
    Ответ написан
    1 комментарий
  • Отправка смс через шлюз Yeastar кириллицей?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Передавать кириллицу надо в кодировке UCS-2 (UCS-2BE). Также надо в первые 6 байт (3 символа) поместить в UDH (User Data Header) информацию о склейке. Это такие байты:

    05 00 03 xx yy zz

    Тут:
    xx - уникальный идентификатор (можно выбирать случайное число от 0 до 255).
    yy - общее количество сегментов (n)
    zz - номер сегмента (1...n)

    Также обычно где-то надо передать data_coding сообщения и признак наличия склейки и/или UDH в теле сообщения (в SMPP, например, для этого используется бит 0x40 в esm_class). С Yeastar не сталкивался, не знаю, как конкретно там это устроено.

    Из-за наличия UDH в теле сообщения максимальная длина сегмента уменьшается на 3 символа и ограничена 67 символов.

    См. также
    https://en.wikipedia.org/wiki/Concatenated_SMS
    https://en.wikipedia.org/wiki/User_Data_Header
    Ответ написан
  • Как получить file_id без отправки сообщения пользователю?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Я решал эту задачу так: при первой отправке файла я его отправлял как файл, запоминая file_id в словаре и в таблице в базе, а при следующей уже имел готовый file_id. При этом я могу в любой момент добавлять файлы, не задумываясь о том, загружал ли я их уже в Telegram или нет.

    files = {}
    def load_files():
      global files
      res = db.execute("SELECT file_name,file_id FROM files")
      files = {}
      for row in res:
        file_name, file_id = row
        files[file_name] = file_id
    
    def save_file(file_name, file_id):
      global files
      db.execute("INSERT INTO files (file_name,file_id) VALUES (?,?) ON CONFLICT(file_name) DO UPDATE SET file_id=excluded.file_id", (file_name, file_id))
      files[file_name] = file_id
    
    load_files()
    
    ...
            if item["photo"] in files:
              file_id = files[item["photo"]]
              print (f" send photo file_name={item['photo']} file_id={file_id}")
              bot.send_photo(call.message.chat.id, file_id)
            else:
              with open(os.path.join("menu", item["photo"]), "rb") as f:
                bot.send_chat_action(call.message.chat.id, "upload_photo")
                r = bot.send_photo(call.message.chat.id, f)
                file_id = r.photo[0].file_id
                save_file(item["photo"], file_id)
                print (f" uploaded photo file_name={item['photo']} file_id={file_id}")
    Ответ написан
    Комментировать
  • Как привязать домен к ip адресу с портом?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Как пить дать нужно для сайта. Ответ: на этом хосте на стандартных портах (80, 443) повесить reverse proxy (nginx, можно apache с mod_proxy, но лучше nginx), который трафик по этому конкретному домену будет прокидывать на самого себя с другим портом.
    Ответ написан
    Комментировать
  • Почему у меня не работает ответ на нажатие на InlineKeyboardButton (Python)?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Inline-кнопки в отличие от обычных не генерируют текстовое сообщение. Их надо ловить через отдельный обработчик callback_query_handler:

    @bot.callback_query_handler(func=lambda call: call.message is not None)
    def my_inline_callback(call):
      chat_id = call.message.chat.id
      user_id = call.from_user.id
      data = call.data
      ...
    Ответ написан
    Комментировать
  • Как заставить CentOS правильно отображать длину кириллических символов в консоли?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Что смотреть:

    locale - показывает текущие параметры локали
    locale -a - показывает весь список доступных локалей
    localectl - утилита от systemd

    Если настроенная локаль отсутствует в общем списке, то locale и некоторые другие приложения (например, perl) будут ругаться на это.

    Чтобы сгенерировать недостающую нужную локаль, можно использовать localedef:

    localedef ru_RU.UTF-8 -f UTF-8 -i ru_RU

    В некоторых системах (в частности, на базе Debian и Gentoo) вместо localedef можно использовать другую утилиту locale-gen. Также в Debian/Ubuntu можно добавить локали галочками в списке с помощью dpkg-reconfigure locales.

    Уже запущенные приложения надо перезапустить, чтобы они увидили новую локаль, в частности, приложения, запускаемые при логине в систему, перезапустятся при следующем входе.
    Ответ написан
    Комментировать
  • Как узнать статус пользователя Telegram (онлайн\оффлайн)?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Bots API не позволяет узнать состояние онлайна пользователя. Это можно узнать только через клиентский API.
    Ответ написан
    Комментировать
  • Ограничение на добавление в группу Telegram?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Это настройки приватности у соответствующего пользователя. Следует попросить пользователя обменяться контактами, или на время это отключить, или попросить добавить другого участника чата, с которым этот пользователь состоит в контактах.
    Ответ написан
    Комментировать
  • Как разобраться с выводом valgrind?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    При попадании в блок:
    if (!result)
    память реально НЕ выделена и free от неё - это попытка освободить память по адресу NULL. Разумеется, это не будет работать.

    upd: Прочитал вопрос ещё раз внимательнее. Надо не забывать делать free в конечном месте использования этого result:

    result = get_next_line();<br>
    ...do_something_with_result...<br>
    free(result);


    Иначе да, при каждом вызове get_next_line будет выделяться новый блок на 2 байта.
    Ответ написан
    3 комментария
  • Как проверить хэш PHP функции crypt на Python?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    В python есть такая же функция в модуле crypt.

    $hash = crypt ($password, $salt);

    from crypt import crypt
    hash = crypt (password, salt)
    Ответ написан
    Комментировать
  • Расшифровывается QRcode в TelegramBotAPI, но расшифровывает характеристики фотографии?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Очевидно, потому что data представляет из себя экземпляр класса Decoded. Думаю, тебе нужно data.data, да ещё и привести тип bytes к строке: data.data.decode()
    Ответ написан
    1 комментарий
  • Какой есть сервис, где можно отправить смс, можно платно?

    shurshur
    @shurshur
    Сисадмин, просто сисадмин...
    Операторы сейчас вовсю борются с массовыми смс с федеральными номерами. Поэтому крупные сервисы не могут это предоставлять надёжно. Если используются сим-банки - то их быстро банят. Отправка через SS7 мимо interconnect сейчас работает очень плохо, остались только какие-то серые схемы, в которых уровень доставки уже ниже 50%.

    Легальный способ - аренда имени у всех операторов. Это дорого, да. Но операторы под предлогом борьбы со спамом вынуждают к этому. Либо придётся соглашаться на общие имена у конкретных сервисов (да, я уже прочитал, что тебе этого не хочется).

    И последний способ, который условно нелегален, но при 10 смс в месяц вряд ли кто-то заметит: воткнуть GSM-модем с симкой в свой компьютер/сервер и отправлять через него.

    Но вообще если это всё для тестирования, то реальная отправка смс вообще непонятно зачем нужна. Сгенерил код в приложении - он появился в логах - ввёл код из логов в клиентском интерфейсе.
    Ответ написан