Добавить поддержку Яндекс Маркета (goods-feedback API)

- app/services/ym.py: клиент Partner API — getGoodsFeedbacks с пагинацией и
  фильтром по дате, updateGoodsFeedbackComment (ответ), deleteGoodsFeedbackComment
  (удаление), обработка новых отзывов по аналогии с WB/Ozon
- воркер ym_worker, включается при заданных YM_API_KEY и YM_BUSINESS_ID
- кнопки отправки/удаления ответа, платформа в сообщении и в таблице,
  статистика /stat и /allstat
- переменные YM_API_KEY, YM_BUSINESS_ID, YM_CHECK_INTERVAL, PRODUCTS_YM_SHEET_LINK
- README и .env.example

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 20:13:38 +03:00
co-authored by Claude Fable 5.1
parent 1098ff4991
commit 4534ab2683
10 changed files with 481 additions and 24 deletions
+33 -6
View File
@@ -11,6 +11,7 @@ from app.handlers.reviews import send_queue_worker, sheet_queue_worker
from app.models import Settings
from app.services.ozon import OzonClient
from app.services.wb import WildberriesClient
from app.services.ym import YandexMarketClient
# Configure logging
logging.basicConfig(
@@ -56,6 +57,25 @@ async def wb_worker():
await asyncio.sleep(config.WB_CHECK_INTERVAL)
async def ym_worker():
ym_client = YandexMarketClient()
while True:
try:
logger.info("Checking for new Yandex Market reviews...")
ym_result = await ym_client.process_new_reviews()
logger.info(
f"Processed {ym_result['processed']} Yandex Market reviews, {ym_result['new']} new"
)
except Exception as e:
logger.error(
f"Error during Yandex Market review check: {e.__class__.__name__}: {e}"
)
logger.info(f"Next check in {config.YM_CHECK_INTERVAL} seconds")
await asyncio.sleep(config.YM_CHECK_INTERVAL)
async def main():
"""Set up and run the bot."""
session = (
@@ -130,13 +150,20 @@ async def main():
},
)
worker_tasks = [
ozon_worker(),
wb_worker(),
send_queue_worker(),
sheet_queue_worker(),
]
# Опрос Яндекс Маркета включается только при заданных ключе и businessId
if config.YM_API_KEY and config.YM_BUSINESS_ID:
worker_tasks.append(ym_worker())
else:
logger.info("YM_API_KEY / YM_BUSINESS_ID not set, Yandex Market polling disabled")
workers = asyncio.ensure_future(
asyncio.gather(
ozon_worker(),
wb_worker(),
send_queue_worker(),
sheet_queue_worker(),
)
asyncio.gather(*worker_tasks)
) # future must be saved to prevent GC
print(f"Workers future: {workers}")