Files
kwork/app/service.py
2026-07-14 13:38:43 +07:00

91 lines
3.1 KiB
Python

from __future__ import annotations
import logging
from app.filters import get_offer_skip_reason
from app.state import SentOffersStore
from app.telegram import TelegramPublisher
from app.sources.base import OfferSource
logger = logging.getLogger(__name__)
class OfferProcessingService:
def __init__(
self,
sources: list[OfferSource],
publisher: TelegramPublisher,
sent_offers_store: SentOffersStore,
include_keywords: list[str],
exclude_keywords: list[str],
min_price_amount: int | None,
) -> None:
self._sources = sources
self._publisher = publisher
self._sent_offers_store = sent_offers_store
self._include_keywords = include_keywords
self._exclude_keywords = exclude_keywords
self._min_price_amount = min_price_amount
async def run_once(self) -> None:
for source in self._sources:
try:
logger.info("Fetching offers from source=%s", source.source_name)
offers = source.fetch_offers()
logger.info("Fetched %s offers from source=%s", len(offers), source.source_name)
except Exception:
logger.exception("Failed to fetch offers from source %s", source.source_name)
continue
skipped_duplicates = 0
skipped_exclude_keyword = 0
skipped_include_keyword = 0
skipped_min_price_amount = 0
published_count = 0
for offer in offers:
if self._sent_offers_store.has(offer.dedup_key):
skipped_duplicates += 1
continue
skip_reason = get_offer_skip_reason(
offer,
self._include_keywords,
self._exclude_keywords,
self._min_price_amount,
)
if skip_reason == "exclude_keyword":
skipped_exclude_keyword += 1
continue
if skip_reason == "include_keyword":
skipped_include_keyword += 1
continue
if skip_reason == "min_price_amount":
skipped_min_price_amount += 1
continue
try:
await self._publisher.publish_offer(offer)
except Exception:
logger.exception("Failed to publish offer %s", offer.dedup_key)
continue
self._sent_offers_store.add(offer.dedup_key)
published_count += 1
logger.info("Published offer %s", offer.dedup_key)
logger.info(
(
"Source %s summary: fetched=%s published=%s skipped_duplicates=%s "
"skipped_exclude_keyword=%s skipped_include_keyword=%s skipped_min_price_amount=%s"
),
source.source_name,
len(offers),
published_count,
skipped_duplicates,
skipped_exclude_keyword,
skipped_include_keyword,
skipped_min_price_amount,
)