• Где я поймал invalid syntax?

    shabelski89
    @shabelski89
    engineer
    лишние пробелы перед await.
    Ответ написан
    1 комментарий
  • Возможно ли игнорировать файл/папку через .gitignore, которые уже есть в репозитории?

    shabelski89
    @shabelski89
    engineer
    Вы можете удалить файл из индекса, то есть при первоначальном init файл будет, а дальше вы убираете его из индекса и файл останется, а дальнейшие изменения с ним не будут отслеживаться.
    git rm --cached <file>
    Ответ написан
    Комментировать
  • Как оформить SQL запрос к PostgreSQL и подставить туда значение переменных?

    shabelski89
    @shabelski89
    engineer
    cursor.execute("SELECT * FROM tkd WHERE street_str LIKE '%s' AND house = %s", (street_str,  house))
    Ответ написан
  • Как получить локальную переменную из цикла for?

    shabelski89
    @shabelski89
    engineer
    result = [re.findall(r"ftp://\d+.\d+.\d+.\d+.\d.\d+", ip) for ip in list]
    print(result)
    Ответ написан
    1 комментарий
  • Проблемка с fetchall(). Можете помочь?

    shabelski89
    @shabelski89
    engineer
    Читаем учебник, а не пишем ботов. Что такое кортежи, списки, срезы.
    example = ('Valentine',)
    example[0]
    'Valentine'
    Ответ написан
    Комментировать
  • Авто дополнение в python?

    shabelski89
    @shabelski89
    engineer
    для варианта 1 с использованием argparse изучайте
    Ответ написан
  • Как передать значение в команду sqlite3?

    shabelski89
    @shabelski89
    engineer
    кровь из глаз :)
    cur.execute("SELECT COUNT(*) FROM users WHERE ? = 1 OR ? = 1 ", ("n7","n8" ))
    xxx = cur.fetchall()
    Ответ написан
    Комментировать
  • Как удалять пользователя из бд после того, как он удалил бота в телеграмме?

    shabelski89
    @shabelski89
    engineer
    О том что он удалил, можно узнать только когда бот отправит сообщение и получит ексепш что он удалён.
    Нужно перехватить exception и вызвать удаление из БД.
    try:
        bot.send_message(user_id, text)
    except telebot.apihelper.ApiException:
        logging.exception(f'Send Notification ERROR - {telebot.apihelper.ApiException}')
        delete_user(user_id)


    где вызывается удаление пользователя из БД, где он вероятно есть для рассылки.
    def delete_user(user_id):
        del_user_query = f'DELETE FROM {users_t} WHERE {users_col["user_id"]} = {user_id};'
        post_sql_query(del_user_query)
    Ответ написан
    Комментировать
  • Как получить значение в словаре, если не знаешь ключ?

    shabelski89
    @shabelski89
    engineer
    Если Вы уверены в том что в словарь отсортирован как нужно, можно забирать данные из списка.
    d = {235454: 11, 6546464: 43}
    list(d.values())
    [11, 43]
    list(d.values())[0]
    11
    Ответ написан
    Комментировать
  • Как добавлять кнопки в клавиатуру в зависимости от данных из базы данных в Telebot?

    shabelski89
    @shabelski89
    engineer
    Предположим Вы знаете как из sqlite полчать данные, обычно при fetchall() получаем список кортежей, например такой: some_data_from_sqlite = [('one',), ('two',), ('ten',)] .
    а уж клавиатуру сделать проще простого:
    import telebot
    from telebot import types
    
    
    API_TOKEN = ""
    bot = telebot.TeleBot(API_TOKEN)
    
    
    @bot.message_handler(commands=['start'])
    def start(message):
        some_data_from_sqlite = [('one',), ('two',), ('ten',)]  # список кортежей из БД
        buttons_dict = {i: x[0] for i, x in enumerate(some_data_from_sqlite)}
        keyboard = types.InlineKeyboardMarkup()
        back_button = types.InlineKeyboardButton(text="Back", callback_data="MainMenu")
        button_list = [types.InlineKeyboardButton(text=x, callback_data=x) for x in buttons_dict.values()] # callback дата понадобится при обработке нажатий на кнопку, но это уже совсем другая история :)
        keyboard.add(*button_list, back_button)
        bot.send_message(chat_id=message.chat.id, text=message.text, reply_markup=keyboard)
    
    
    if __name__ == "__main__":
        try:
            bot.polling(none_stop=True)
        except Exception as e:
            print(e)
    Ответ написан
    5 комментариев
  • Как получить данные из postgresql в python?

    shabelski89
    @shabelski89
    engineer
    На скорую руку
    import psycopg2
    from datetime import datetime, timedelta
    from pprint import pprint
    
    
    def get_dt(dt: str):
        return datetime.strptime(dt, '%Y%m%d')
    
    
    def get_dt_delta(dt: datetime, s=1, e=4):
        return dt - timedelta(days=s), dt + timedelta(days=e)
    
    
    def execute(config, sql, param=None, select_mode=True):
        connection = None
        try:
            connection = psycopg2.connect(**config)
            cursor = connection.cursor()
            if param:
                cursor.execute(sql, param)
            else:
                cursor.execute(sql)
            if select_mode:
                return cursor.fetchall()
        except Exception as E:
            print(E)
        finally:
            connection.close()
    
    
    def get_devices():
        devices_q = "SELECT * from devices LEFT JOIN devatt on devices.dev = devatt.dev " \
                    "WHERE devatt.att = 'otherinfo' AND devatt.value like '0%'"
        return [x[0] for x in execute(cfg, devices_q)]
    
    
    def generate_rep(devs, period):
        r = {}
        period_dt = get_dt(period)
        period_s, period_e = get_dt_delta(period_dt)
        for dev in devs:
            q = 'SELECT * from rawdata where deveui = %s and time between %s AND %s ORDER BY id DESC'
            rawdata = execute(config=cfg, sql=q, param=(dev, period_s, period_e))
            r[dev] = rawdata
        return r
    
    
    if __name__ == "__main__":
        cfg = dict(user="pguser", password="localpass", host="127.0.0.1", port="5432", database="wan_server")
        devices = get_devices()
        date = '20220308'
        result = generate_rep(devs=devices, period=date)
        pprint(result)


    1. смотрите как правильно работать с датой и временем
    2. не используйте интерполяцию в sql запросе
    Ответ написан
    1 комментарий
  • SQLALCHEMY как организовать работу с сессией?

    shabelski89
    @shabelski89
    engineer
    Без примера кода сложно понять, но я использую декоратор для функций работы с БД.
    def catch_session(func):
        """Decorator for Session"""
        @wraps(func)
        def wrapper(self, *args, **kwargs):
            print(f"Try calling db func: {func.__name__}")
            result = func(self, *args, **kwargs)
            try:
                self.session.commit()
                print(f"Success calling db func: {func.__name__}\n")
            except SQLAlchemyError as e:
                print(f"Error - {e}\n")
                self.session.rollback()
            finally:
                self.session.close()
            return result
        return wrapper


    просто оборачиваете им функцию и он сам делает commit если не было ошибок, если было то rollback и сообщение об ошибке.

    взято отсюда
    Ответ написан
    Комментировать
  • Почему бот не выполняет команду повторно?

    shabelski89
    @shabelski89
    engineer
    Код практически невозможно читать, куча копипастов даже из моих старых ответов :) ).

    На вашем текущем уровне понимания ЯП я бы предложил почистить код.
    выносим БД и все данные в отдельный модуль и наводим порядок.
    tanks_db.py

    import sqlite3
    from sqlite3 import Error
    from time import ctime
    
    
    def post_sql_query(sql_query, database='bazaa.db'):
        with sqlite3.connect(database) as connection:
            cursor = connection.cursor()
            try:
                cursor.execute(sql_query)
            except Error as E:
                print(E)
            result = cursor.fetchall()
            return result
    
    
    def register_user(user_id, username, first_name, last_name):
        user_check_query = f'SELECT * FROM USERS WHERE user_id = {user_id};'
        user_check_data = post_sql_query(user_check_query)
        if not user_check_data:
            insert_to_db_query = f'INSERT INTO USERS (user_id, username, first_name, last_name, reg_date) ' \
                                 f'VALUES ({user_id}, "{username}", "{first_name}", "{last_name}", "{ctime()}");'
            post_sql_query(insert_to_db_query)
    
    
    def user_exists(user_id):
        if get_user_name(user_id) is None:
            return False
        return True
    
    
    def get_user_name(user_id):
        user_check_query = f'SELECT username FROM USERS WHERE user_id = {user_id};'
        result = post_sql_query(user_check_query)
        if result is None:
            return None
        return result[0]
    
    
    
    users_tables = '''CREATE TABLE IF NOT EXISTS USERS 
                            (user_id INTEGER PRIMARY KEY NOT NULL,
                            username TEXT,
                            first_name TEXT,
                            last_name TEXT,
                            reg_date TEXT);'''
    
    post_sql_query(users_tables)
    
    tanks_tables = '''CREATE TABLE IF NOT EXISTS TANKS 
                            (name TEXT PRIMARY KEY, info TEXT, photo TEXT);'''
    
    post_sql_query(tanks_tables)
    tanks = [
        {'name': 'Т-26', 'info': '<======Т-26======>\n\nМасса (т) - 9.26\n\nПрочность - 270 ед.\n\nМощность двигателя (л.с.) - 130\n\nМаксимальная скорость (км/ч) - 36\n\nБронепробиваемость базовым снарядом (мм) - 37-51\n\nУрон базовым снарядом - 26-44\n\nСкорострельность орудия (выстр/мин) - 10.3', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\R09_T-26.png'},
        {'name': 'БТ-2', 'info': '<======БТ-2======>\n\nМасса (т) - 12.93\n\nПрочность - 380 ед.\n\nМощность двигателя (л.с.) - 350\n\nМаксимальная скорость (км/ч) - 44\n\nБронепробиваемость базовым снарядом (мм) - 37-51\n\nУрон базовым снарядом - 38-63\n\nСкорострельность орудия (выстр/мин) - 11.8', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r08_bt-2_image_resized.png'},
        {'name': 'БТ-7', 'info': '<======БТ-7======>\n\nМасса (т) - 15.34\n\nПрочность - 470 ед.\n\nМощность двигателя (л.с.) - 375\n\nМаксимальная скорость (км/ч) - 45\n\nБронепробиваемость базовым снарядом (мм) - 48-64\n\nУрон базовым снарядом - 45-75\n\nСкорострельность орудия (выстр/мин) - 13.0', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r03_bt-7_image_resized.png'},
        {'name': 'А-20', 'info': '<======А-20======>\n\nМасса (т) - 18.57\n\nПрочность - 520 ед.\n\nМощность двигателя (л.с.) - 400\n\nМаксимальная скорость (км/ч) - 45\n\nБронепробиваемость базовым снарядом (мм) - 71-97\n\nУрон базовым снарядом - 90-150\n\nСкорострельность орудия (выстр/мин) - 7.8', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r12_a-20_image_resized.png'}
    ]
    
    for tank in tanks:
        name = tank['name']
        info = tank['info']
        photo = tank['photo']
        post_sql_query(f'INSERT OR IGNORE INTO TANKS (name, info, photo) VALUES("{name}","{info}","{photo}")')



    далее пишем основную логику, в целом там делов на 1 час, форматирование вывода и наполнение БД сделать.

    tanks_bot.py

    import os.path
    import telebot
    from telebot import types
    from tanks_bd import *
    
    
    API_TOKEN = ""
    bot = telebot.TeleBot(API_TOKEN)
    
    
    def get_photo(path):
        try:
            if os.path.exists(path):
                return open(path, 'rb')
        except Exception as E:
            print(E)
            return False
    
    
    def get_main_keyboard():
        keyboard_main = types.InlineKeyboardMarkup()
        tanks_menu = types.InlineKeyboardButton('Танки', callback_data="Tanks")
        profile_button = types.InlineKeyboardButton('Профиль', callback_data="Profile")
        keyboard_main.add(profile_button, tanks_menu)
        return keyboard_main
    
    
    @bot.message_handler(commands=['start'])
    def get_text_messages(message):
        username = message.from_user.first_name
        register_user(message.from_user.id, message.from_user.username, username, message.from_user.last_name)
        keyboard = get_main_keyboard()
        bot.send_message(message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
    
    @bot.callback_query_handler(func=lambda call: True)
    def callback_inline(call):
        if call.data == "MainMenu":
            keyboard = get_main_keyboard()
            username = call.message.chat.first_name
            bot.send_message(call.message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
        if call.data == "Profile":
            profile_query = f'SELECT * FROM USERS WHERE user_id = {call.message.chat.id};'
            profile = post_sql_query(profile_query)
            username, first_name, last_name = profile[0]
            keyboard = get_main_keyboard()
            bot.send_message(call.message.chat.id,
                             f'*username*\n{username}\n*first_name*\n{first_name}\n*last_name*\n{last_name}',
                             reply_markup=keyboard)
    
        if call.data == "Tanks":
            tanks_query = f'SELECT distinct(name) FROM TANKS;'
            tanks_result = post_sql_query(tanks_query)
            keyboard = types.InlineKeyboardMarkup()
            back_button = types.InlineKeyboardButton(text="Back", callback_data="MainMenu")
            button_list = [types.InlineKeyboardButton(text=elem[0], callback_data=elem[0]) for elem in tanks_result]
            keyboard.add(*button_list, back_button)
            bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
                                  text=call.message.text, reply_markup=keyboard)
    
        if call.data:
            check_data = f'SELECT name, info, photo FROM TANKS WHERE name = "{call.data}";'
            check = post_sql_query(check_data)
            if check:
                name, info, photo = check[0]
                bot.send_message(call.message.chat.id, f'*Name*\n{name}\n*Info*\n{info}')
                if get_photo(photo):
                    bot.send_photo(call.message.chat.id, get_photo(photo))
                keyboard = get_main_keyboard()
                username = call.message.chat.first_name
                bot.send_message(call.message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
    
    if __name__ == "__main__":
        try:
            bot.polling(none_stop=True)
        except Exception as e:
            print(e)


    622853c0baf07174276544.png
    Ответ написан
    Комментировать
  • Как "попросить" python код, при вводе команды " start" автоматически заносить в базу данных айди пользователя?

    shabelski89
    @shabelski89
    engineer
    То что Вы спрашиваете называется авто_инкремент ,
    но он в данном случае не очень нужен, так как user_id уникальный в телеграм, проще использовать в качестве ключа его - смотри пример кода тут. Нужно 1 раз создать таблицу create_tables и потом наполнять её функцией register_user.

    Если же надумаете добавить свой ид на основе автоинкремента, то просто изменить в коде как создаётся таблица и делает инсерт.
    Ответ написан
    Комментировать
  • Как и з телеграм подтягивать телефон?

    shabelski89
    @shabelski89
    engineer
    1 Можно ли сделать так, чтобы в БД подтягивалось имя?
    Да
    2 Можно ли сделать так чтобы в БД подтягивался телефон?
    Телефон можно получить только через запрос, либо человек нажмёт поделиться телефоном, либо нужно сделать кнопку поделиться телефоном
    3 Можно ли сделать так чтобы в БД подтягивался юзернейм?
    Да
    В телеге найти бота @ShowJsonBot и отправить ему сообщение, в ответ вы получит JSON с теми полями которые можно выцепить.
    Ответ написан
    Комментировать
  • Как передать путь до файлов скрипту на питоне через контекстное меню windows?

    shabelski89
    @shabelski89
    engineer
    я тоже думаю что загвоздка в винде, но вопрос как обойти её питоном ?
    может через синглетон ?
    что будет при таком коде ?
    from pdf2image import convert_from_path
    import os
    from sys import argv
    
    
    class SingletonMeta(type):
        """
        Класс Одиночка, для запуска единственного экземпляра
        """
    
        _instances = {}
    
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instances:
                instance = super().__call__(*args, **kwargs)
                cls._instances[cls] = instance
            return cls._instances[cls]
    
    
    class Converter(metaclass=SingletonMeta):
        CONST = 200
        POPPLER_PATH = r'C:\Program Files\poppler-0.68.0\bin'
    
        def convert_file(self):
            """
            Метод для конвертации файла pdf в картинки постранично
            """
    
            print("-" * 50)
            print('Конвертирование файла ', argv[1])
            print("-" * 50)
    
            filepath = argv[1]
            path = os.path.dirname(filepath)
            full_filename = os.path.basename(path)
            filename_without_extension = os.path.splitext(full_filename)[0]
    
            # конвертация и сохранние файлов
            pages = convert_from_path(path, self.CONST, poppler_path=self.POPPLER_PATH)
            if not os.path.isdir(filename_without_extension):
                print("-" * 50)
                print("Конвертирование завершено!")
                print("-" * 50)
                print(f"Создание папки {filename_without_extension} под файлы картинок")
                try:
                    os.mkdir(filename_without_extension)
                except OSError as E:
                    print(E)
            print("-" * 50)
    
            for i, page in enumerate(pages):
                print(f"Сохранение страницы {i + 1} как картинки")
                converted_filename = f"{full_filename}_{i + 1}.jpg"
                page.save(os.path.join(path, full_filename, converted_filename), 'JPEG')
            print("-" * 50)
            print('Сохранение завершено!')
            print("-" * 50)
    
    
    if __name__ == "__main__":
        s = Converter()
        s.convert_file()
    Ответ написан
  • Как узнать какой ip или host?

    shabelski89
    @shabelski89
    engineer
    Это не ip адрес, вот тут минимально доступно написано
    Ответ написан
    Комментировать