added alerts collection dsql suggested
This commit is contained in:
1 parent
6ad9cf5d6d
commit
15acb97c86
2 files changed
+6
-66
No files matched your search
@@ -162,10 +162,10 @@ async def write_alert_ops(alert_ops: list[UpdateOne]):
|
|||||||
await get_collection(ALERTS_COLLECTION_NAME).bulk_write(
|
await get_collection(ALERTS_COLLECTION_NAME).bulk_write(
|
||||||
alert_ops, ordered=False
|
alert_ops, ordered=False
|
||||||
)
|
)
|
||||||
except BulkWriteError as error:
|
except BulkWriteError as exc:
|
||||||
real_errors = [
|
real_errors = [
|
||||||
write_error
|
write_error
|
||||||
for write_error in error.details["writeErrors"]
|
for write_error in exc.details["writeErrors"]
|
||||||
if write_error.get("code") != 11000
|
if write_error.get("code") != 11000
|
||||||
]
|
]
|
||||||
if real_errors:
|
if real_errors:
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime, timedelta, timezone
|
|
||||||
from typing import Awaitable, Callable, Iterable
|
from typing import Awaitable, Callable, Iterable
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@@ -16,9 +15,7 @@ from monitor_utils.config import (
|
|||||||
set_logger_levels,
|
set_logger_levels,
|
||||||
)
|
)
|
||||||
from monitor_utils.constants import (
|
from monitor_utils.constants import (
|
||||||
BUCKET_WEBHOOK_MAP,
|
|
||||||
EXPECTED_TASK_ERRORS,
|
EXPECTED_TASK_ERRORS,
|
||||||
FLAG_WEBHOOK_MAP,
|
|
||||||
LOGGING_LEVEL,
|
LOGGING_LEVEL,
|
||||||
)
|
)
|
||||||
from monitor_utils.database import get_collection
|
from monitor_utils.database import get_collection
|
||||||
@@ -105,73 +102,19 @@ def setup_config(
|
|||||||
return category_names, config["channels"], collection
|
return category_names, config["channels"], collection
|
||||||
|
|
||||||
|
|
||||||
def get_channel_id(
|
|
||||||
product: Product, channel_ids: dict, use_price_drop_bucket: bool = False
|
|
||||||
) -> str:
|
|
||||||
"""Resolve the Discord channel id for a product based on its attributes.
|
|
||||||
|
|
||||||
Checks flags in priority order: app exclusive, sold out, event ending
|
|
||||||
within a day, availability flag mappings, then the percentage or price
|
|
||||||
drop bucket. A KeyError on bucket lookup is acceptable because each
|
|
||||||
monitor's percentage filtering guarantees the bucket exists.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
product: Built product whose attributes select the channel.
|
|
||||||
channel_ids: Mapping of channel keys to a channel id or list of ids.
|
|
||||||
use_price_drop_bucket: Route to the price drop bucket instead of the
|
|
||||||
percentage bucket.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The resolved channel id.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if product.availability.app_exclusive:
|
|
||||||
return get_single_channel_id(channel_ids["appExclusive"])
|
|
||||||
|
|
||||||
if product.availability.available is False:
|
|
||||||
return get_single_channel_id(channel_ids["soldOut"])
|
|
||||||
|
|
||||||
if product.timing.end_date:
|
|
||||||
now = datetime.now(timezone.utc)
|
|
||||||
if (product.timing.end_date - now) <= timedelta(days=1):
|
|
||||||
return get_single_channel_id(channel_ids["event"])
|
|
||||||
|
|
||||||
for attr, key in FLAG_WEBHOOK_MAP:
|
|
||||||
if getattr(product.availability, attr, False):
|
|
||||||
return get_single_channel_id(channel_ids[key])
|
|
||||||
|
|
||||||
percentage = product.metadata.percentage or 0
|
|
||||||
percentage_bucket = min(90, (percentage // 10) * 10)
|
|
||||||
if use_price_drop_bucket:
|
|
||||||
return get_single_channel_id(channel_ids[BUCKET_WEBHOOK_MAP["price_drop"]])
|
|
||||||
|
|
||||||
return get_single_channel_id(channel_ids[BUCKET_WEBHOOK_MAP[percentage_bucket]])
|
|
||||||
|
|
||||||
|
|
||||||
def get_single_channel_id(value: str | list[str]) -> str:
|
|
||||||
"""Return the first channel id when given a list, else the value itself."""
|
|
||||||
|
|
||||||
if isinstance(value, list):
|
|
||||||
return value[0]
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
def build_product_details(
|
def build_product_details(
|
||||||
product: dict,
|
product: dict,
|
||||||
channel_ids: dict,
|
|
||||||
min_percentage: int,
|
min_percentage: int,
|
||||||
min_price_drop: float | None = None,
|
min_price_drop: float | None = None,
|
||||||
) -> Product | None:
|
) -> Product | None:
|
||||||
"""Build a Product from a Mongo document if it passes discount thresholds.
|
"""Build a Product from a Mongo document if it passes discount thresholds.
|
||||||
|
|
||||||
Skips documents with a missing or zero original price. Passing requires
|
Skips documents with a missing or zero original price. Passing requires
|
||||||
meeting min_percentage, or min_price_drop when provided. The resolved
|
meeting min_percentage, or min_price_drop when provided. Channel routing
|
||||||
channel id is attached to the product's metadata before returning.
|
is owned by the consumer bot; no channel id is attached here.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
product: Mongo document for the product.
|
product: Mongo document for the product.
|
||||||
channel_ids: Mapping of channel keys passed to get_channel_id.
|
|
||||||
min_percentage: Minimum discount percentage to pass.
|
min_percentage: Minimum discount percentage to pass.
|
||||||
min_price_drop: Optional minimum absolute price drop to pass.
|
min_price_drop: Optional minimum absolute price drop to pass.
|
||||||
|
|
||||||
@@ -227,9 +170,6 @@ def build_product_details(
|
|||||||
member_deal=product["memberDeal"],
|
member_deal=product["memberDeal"],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
built.metadata.channel_id = get_channel_id(
|
|
||||||
built, channel_ids, passes_price_drop and not passes_percentage
|
|
||||||
)
|
|
||||||
return built
|
return built
|
||||||
|
|
||||||
|
|
||||||
@@ -279,8 +219,8 @@ async def execute_monitor_logic(
|
|||||||
if pre_task_func:
|
if pre_task_func:
|
||||||
try:
|
try:
|
||||||
await pre_task_func(session=session, **kwargs)
|
await pre_task_func(session=session, **kwargs)
|
||||||
except EXPECTED_TASK_ERRORS as error:
|
except EXPECTED_TASK_ERRORS as exc:
|
||||||
LOGGER.warning("failed to get products", exc_info=error)
|
LOGGER.warning("failed to get products", exc_info=exc)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOGGER.exception("unexpected error")
|
LOGGER.exception("unexpected error")
|
||||||
raise
|
raise
|
||||||
|
|||||||
Reference in new issue
Block a user