Задать вопрос
  • Как проводить тесты моделей, где в переопределенном .save() сохранение используется 2 раза?

    Vindicar
    @Vindicar
    RTFM!
    Ты в setUp() не очищаешь тестовую базу? Т.е. к моменту второго теста у тебя остаются данные после первого?
    Это плохая идея.
    Ответ написан
  • Как настроить logger python на запись LEVEL в разные файлы?

    Vindicar
    @Vindicar
    RTFM!
    нужно делать кастомный фильтр.
    Ответ написан
    Комментировать
  • Почему не работает код?

    Vindicar
    @Vindicar
    RTFM!
    Ну написано же прямым текстом
    TypeError [CLIENT_MISSING_INTENTS]: Valid intents must be provided for the Client.

    Интенты боту не прописал.
    Ответ написан
    Комментировать
  • Как реализовать разные скрипты Telegram bot'а в нескольких файлов?

    Vindicar
    @Vindicar
    RTFM!
    Проблема в том, что тебе нужно продекорировать функции через @bot.чтототам, но другие файлы ничего не знают о боте, так как он описан в главном файле. Так?
    Нужно учесть, как работает декоратор. Код вроде
    @bot.message_handler(commands=['anketaone'])
    def null_anketa_step(message):
        pass

    на самом деле работает примерно так:
    temp_wrapper = bot.message_handler(commands=['anketaone'])
    def null_anketa_step(message):
        pass
    null_anketa_step = temp_wrapper(null_anketa_step)

    Т.е. иными словами, декоратор - это просто вызов функции, в которую передаётся функция или класс!
    Тогда самый простой способ будет таким:
    def null_anketa_step(message):
        pass
    #какой-то другой обработчик
    def some_other_handler(message):
        pass
    
    def init_bot(bot):
        #а в этой функции мы регистрируем обработчики
        bot.message_handler(commands=['anketaone']) (null_anketa_step)
        #обрати внимание на две пары скобок. Вызов bot.message_handler() возвращает функцию (wrapper),
        #и мы эту функцию тут же вызываем, передавая в неё обработчик
        bot.message_handler(commands=['somethingelse']) (some_other_handler)

    Тогда в главном файле ты делаешь примерно так:
    bot = ........ #создаём бота
    from second_file import init_bot as init_second #импортируем второй файл
    #функцию импортируем под другим именем, чтобы не было коллизий между файлами
    init_second(bot) #вызываем функцию регистрации init_bot()
    
    if __name__=='__main__':
        bot.polling(none_stop=True)
    Ответ написан
    5 комментариев
  • Как сделать что бы бот в дискорде выдавал роли после правильного ответа на вопрос?

    Vindicar
    @Vindicar
    RTFM!
    Нужно хранить базу пользователей, и для каждого пользователя хранить id, состояние и метку времени.
    Состояние может быть одно из указанных:
    * стартовое - пользователь ничего не сделал
    * пользователю был задан вопрос
    * пользователь получил роль, тогда поле времени хранит момент, когда роль была получена.

    Тогда при реакции на команду или на сообщение ты ищешь ID пользователя в базе, и проверяешь, что он находится в корректном состоянии. Т.е. если реагируешь на личку, то пользователь должен быть в состоянии "задан вопрос". В нужные моменты сохраняешь в базу новое состояние, например, "задан вопрос" -> "выдана роль".
    Чтобы снять роль, время от времени ищешь в базе пользователей в состоянии "выдана роль", у которых с момента выдачи прошло достаточно много времени, снимаешь им роль и записываешь в базу новое состояние (стартовое).
    Ответ написан
    4 комментария
  • Возможно ли собрать python скрипт со всеми зависимостями в один файл?

    Vindicar
    @Vindicar
    RTFM!
    Нельзя, так как среди зависимостей могут быть модули, написанные не на питоне, а на C. Они зависят от ОС и архитектуры проца.
    Можно создать виртуальное окружение на линуксе и поставить зависимости туда, а не прямо в систему.
    Либо можно использовать докер образ, но я не в курсе как докер дружит с виндой, так как не пользовался. Опять же, докер - штука довольно ресурсоемкая, и полезна только когда часто таскаешь рабочий проект туда-сюда.
    Ответ написан
  • Как изменить название категории?

    Vindicar
    @Vindicar
    RTFM!
    В доках всё есть. Получаешь категорию (в терминологии discord.py категория - это разновидность канала), потом редактируешь.
    Ответ написан
  • Как найти объект по координатам в tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Всё что мне приходит в голову - перебрать все виджеты и найти те, чей прямоугольник содержит искомую точку.
    winfo_x()/winfo_y() - позиция виджета относительно родительского виджета.
    winfo_rootx()/winfo_rooty() - если не путаю, позиция виджета относительно начала экрана.
    winfo_width()/winfo_height() - текущий размер виджета
    winfo_children() - список дочерних виджетов для данного виджета.

    Но зачем тебе это понадобилось? Может, есть способ попроще?
    Ответ написан
    3 комментария
  • Что делать если у всех работает, а у меня нет?

    Vindicar
    @Vindicar
    RTFM!
    unexpected indent - у тебя вставлен отступ там, где ему не место.
    Отступ после декоратора не требуется.
    Т.е. вместо
    @bot.event
        async def on_ready():
            #тело функции
    должно быть
    @bot.event
    async def on_ready():
        #тело функции
    Ответ написан
  • Как выполнить подключение через подключения putty?

    Vindicar
    @Vindicar
    RTFM!
    Посмотри в сторону утилиты plink, она вроде входит в пакет putty.

    Либо посмотри в сторону SSH agent forwarding.
    Ответ написан
    Комментировать
  • Как правильно прописать проверку ввода чисел на питоне для ТГ бота?

    Vindicar
    @Vindicar
    RTFM!
    try:
      v = int(message.text)
      #на случай если тебе подойдёт не всякое число
      if v < 0 or v > 99: 
        raise ValueError()
    except ValueError:
      bot.send_message(message.chat.id, "Не число, или недопустимое число.")
    else:
      bot.send_message(message.chat.id, f"Ты ввел число {v}")
    Ответ написан
    Комментировать
  • Как создать базу ответов?

    Vindicar
    @Vindicar
    RTFM!
    Ну если делать красиво, я бы сделал структуру такого вида:
    [
      {
        "inputs" : [ "привет", "здорово" ],
        "responses" : [ "привет {0}", "и тебе приветы" ]
      },
      {
        "inputs" : [ "пока" ],
        "responses" : [ "досвидос, {0}", "и тебе удачи!" ]
      },
    ]

    inputs - это список регулярных выражений, описывающих входящее сообщение.
    responses - это список строк-ответов.

    Идея такая:
    1. входящее сообщение проверяется на соответствие всем регулярным выражениям поочередно
    2. Если выражение совпало, выбирается случайная строка из числа ответов
    3. с помощью метода format() в строку подставляется имя отправителя сообщения
    4. результат отправляется как ответ на сообщение.

    Загружать вышеописанную структуру данных удобно с помощью модуля json.
    Ответ написан
    Комментировать
  • Аргумент пользователя в переменной?

    Vindicar
    @Vindicar
    RTFM!
    Если ссылка одна и кратковременная:
    current_url = None #храним ссылку в глобальной переменной
    @slash.slash(name = 'lastmap', description = 'последняя версия карты', options = [{"name": "ur", "description": "ссылка", "type": 3, "required": True}], guild_ids = [907669402181316638])
    @client.command(aliase = ['lastmap'])
    @commands.has_any_role(907669402181316638)
    async def lastmap(ctx, *, ur):
      global current_url
      id = ctx.author.display_name
      current_url = ur
      embedVar = discord.Embed(title="Карта", description=f"{id}, карта обновлена, ссылка: {current_url}")
      embedVar.set_image(url='https://media.discordapp.net/attachments/902258027648917524/907969211312271360/unknown.png')
      await ctx.send(embed=embedVar)    
    
    @slash.slash(name = 'map', description = 'последняя версия карты', options = [{"name": "text", "description": "текст", "type": 3, "required": True}], guild_ids = [907669402181316638])
    @client.command(aliase = ['map'])
    @commands.has_any_role(907669402181316638)
    async def map(ctx, *, text):
      global current_url
      id = ctx.author.display_name
      if current_url: #проверяем, задана ли карта
        embedVar = discord.Embed(title="Карта", description=f"Держи карту, {id}. Только зачем ты написал {text}?")
        embedVar.set_image(url=f'{current_url}')
        await ctx.send(embed=embedVar)
      else:
        await ctx.send(f"Извини, {id}, карта ещё не задана.")
    Ответ написан
    Комментировать
  • Как поставить скрипт на паузу в Python?

    Vindicar
    @Vindicar
    RTFM!
    > ввёл значение в поле input, а после нажатие кнопки "Подтвердить"
    1. Зависит от того, какой GUI фреймворк ты используешь.
    2. Зачем пауза, когда можно просто поместить нужные операции в реакцию на кнопку? Хотя, если тебе GUI нужен только для ввода данных, можно исхитриться - но тут уже см. п. 1.
    Ответ написан
    Комментировать
  • Почему не работает условие elif?

    Vindicar
    @Vindicar
    RTFM!
    Потому что если число больше 18, оно также больше 10.
    Ответ написан
    Комментировать
  • Добавление прав при создании канала?

    Vindicar
    @Vindicar
    RTFM!
    nom = random.randint(1000, 99999)
    Рано или поздно словите коллизию. Хотя бы проверяйте наличие канала и перегенерируйте.
    А вообще, вы ставите права только конкретно для автора, но не сносите права по умолчанию, и не ставите права для роли.
    Ответ написан
  • Почему не видит путь/экзешник?

    Vindicar
    @Vindicar
    RTFM!
    Юра Милевский, вынеси код ядра в отдельный поток (через threading) или в отдельный процесс (через multiprocessing). В главном потоке/процессе оставь GUI.
    Общение организуй через threading.Queue или multiprocessing.Queue (смотря что используешь).
    У тебя GUI задаёт только настройки ядра, ведь так? Тогда ты когда опльзователь что-то меняет в GUI, ты кладёшь в очередь кортеж вида ("имя параметра", "значение параметра"). Ядро в свободное время проверяет наличие новых элементов в Queue, извлекает эти кортежи, и запоминает новые настройки уже локально у себя (например, в словаре). Ну и использует этот словарь, когда потребуется.

    Если потребуется усложнить взаимодействие, то усложни структуру данных, которую передаешь. Например, кортеж будет иметь вид ("Имя команды", ["параметры", "команды"]). Ядро должно будет эту команду уже как-то интерпретировать и выполнить. Так или иначе, ключевая идея такая - передаёшь через очередь только примитивные типы вроде строк и чисел, а также кортежи, списки и словари.

    А если понадобится передать что-то от ядра в GUI, то используй отдельную очередь, которую GUI будет проверять, а ядро - наполнять.
    Ответ написан
  • Приветствую, пишу бота для дискорда на Python, не работает кик, в чем моя ошибка?

    Vindicar
    @Vindicar
    RTFM!
    lolikcheck09, кнопка </>

    Далее, я что-то не пойму с каким клиентом ты работаешь?
    Или ты работаешь с MyClient(), или ты работаешь с discord.ext.commands.Bot()?
    Потому что Bot() - это потомок Client(). Ты используешь его декоратор, т.е. опдписываешь свои функции на его события, но при этом не запускаешь bot, а запускаешь экземпляр MyClient().
    Ответ написан
  • Как реализовать выполнение процессов асинхронно?

    Vindicar
    @Vindicar
    RTFM!
    Ну если тебе нужна очередь, то asyncio.Queue в руки - или её эквивалент из threading, если решишь использовать потоки.
    Асинхронность поможет только если обработка элементов содержит большую долю ввода/вывода.
    Ответ написан
  • Как выполнять последовательную проверку данных в Google Seets?

    Vindicar
    @Vindicar
    RTFM!
    У меня получилось 4000 строк на 76 ключей

    Я надеюсь, вы знакомы с понятием цикла? o_O
    range='A3:A3',

    Просто генерируете значение range.
    for row in range(3, 130):
        values_guid = service.spreadsheets().values().get(
            spreadsheetId=spreadsheet_id,
            range=f'A{row}:A{row}',
            majorDimension='COLUMNS'
        ).execute()
        #ну и так далее

    Вместо цикла for по фиксированному диапазону можно сделать цикл while, и прерывать его когда наткнётесь на пустую ячейку. Тогда не придётся прописывать количество ячеек.
    Ответ написан
    3 комментария