我编写了一个与 Trello API 配合使用的机器人。在机器人中拥有管理面板的用户可以更新 Trello 中的看板(我们将其称为一种数据库),使用必要条件的用户也可以使用 API 在 Trello 中找到必要的数据。该机器人非常慢。我收到 1 条消息并等待 5-10 秒。并且此类数据有大量
这个特定的部分可以工作很长时间
# Функция для отправки карточек Trello
async def send_trello_cards_page(message: types.Message,user_id: int, list_id: str, price_range: tuple, start_index: int = 0):
url = f"https://api.trello.com/1/lists/{list_id}/cards"
params = {
"key": TRELLO_API_KEY,
"token": TRELLO_API_TOKEN,
"attachments": "true"
}
headers = {"Cookie": COOKIE}
response = requests.get(url, params=params)
if response.status_code != 200:
await message.answer("Не удалось получить данные с Trello.")
return
cards = response.json()
if not cards:
await message.answer("Список Trello пуст.")
return
# Сохраняем состояние пользователя при первом вызове
if user_id not in user_states:
user_states[user_id] = {
"cards": cards,
"index": 0
}
# Получаем отфильтрованные карточки
filtered_cards = user_states[user_id].get("filtered_cards")
if filtered_cards is None: # Фильтруем карточки только один раз
filtered_cards = [
card for card in cards
if price_range[0] <= extract_price_from_description(card.get('desc', '')) <= price_range[1]
]
# Применяем фильтр по количеству комнат, если это не квартира
current_rooms = user_filters[user_id].get("rooms", "1")
property_type = user_filters[user_id].get("type", "apartment") # Тип недвижимости
if property_type != "apartment":
if "и более" in current_rooms:
min_rooms = int(current_rooms.split()[0]) # Извлекаем число перед "и более"
filtered_cards = [
card for card in filtered_cards
if extract_rooms_from_description(card.get('desc', '') or '0').isdigit()
and int(extract_rooms_from_description(card.get('desc', ''))) >= min_rooms
]
else:
current_rooms_int = int(current_rooms)
filtered_cards = [
card for card in filtered_cards
if extract_rooms_from_description(card.get('desc', '') or '0').isdigit()
and int(extract_rooms_from_description(card.get('desc', ''))) == current_rooms_int
]
user_states[user_id]["filtered_cards"] = filtered_cards
# Если отфильтрованных карточек нет, отправляем сообщение с предложением изменить фильтры
if not filtered_cards:
await message.answer(
"По таким фильтрам нет объявлений. Попробуйте другие фильтры:",
reply_markup=create_apartment_filters_inline(user_filters[user_id]) # Фильтры для квартиры
)
await message.answer(
"Выберите действие:",
reply_markup=create_search_keyboard() # Обычная клавиатура для поиска
)
return
# Отправляем карточки по 5 штук
end_index = min(start_index + 5, len(filtered_cards))
selected_cards = filtered_cards[start_index:end_index]
for card in selected_cards:
caption = f"{card['name']}\n{card.get('desc', 'Без описания')}"
photos = []
for attachment in card.get('attachments', []):
if attachment.get('isUpload') and attachment['url'].endswith(('jpg', 'jpeg', 'png')):
image_path = download_image_in_memory(attachment['url'], headers)
if image_path:
if not photos:
photos.append(InputMediaPhoto(InputFile(image_path), caption=caption))
else:
photos.append(InputMediaPhoto(InputFile(image_path)))
if photos:
if len(photos) >= 1:
await message.answer_media_group(media=photos)
else:
await message.answer_photo(photo=photos[0].media, caption=photos[0].caption)
# Обновляем текущий индекс
user_states[user_id]["index"] = end_index
# Проверяем, есть ли еще карточки
total_cards = len(filtered_cards)
remaining = total_cards - end_index
if remaining > 0:
next_count = min(5, remaining)
await message.answer(
f"Мы отправили вам {end_index} объявлений из {total_cards}. Отправить еще {next_count}?",
reply_markup=create_continue_keyboard()
)
else:
await message.answer("Все объявления отправлены.")
user_states.pop(user_id, None)
# Полная очистка данных пользователя из user_states
if user_id in user_states:
del user_states[user_id] # Удаляем все данные пользователя
# Функция для извлечения количества комнат из описания карточки
def extract_rooms_from_description(description: str) -> str:
# Список ключевых фраз для поиска
patterns = [
r'Комнат:\s*(\d+)', # Ищем "Комнат: X"
r'Комнаты:\s*(\d+)', # Ищем "Комнаты: X"
r'Количество комнат:\s*(\d+)' # Ищем "Количество комнат: X"
]
for pattern in patterns:
match = re.search(pattern, description)
if match: # Если нашли совпадение
return match.group(1)
# Если ничего не найдено, возвращаем значение по умолчанию
return "1"