Bug fix
- Validate and enforce positive price for SPECIFIC_PRICE alerts - improve error handling and alert squelching logic.
This commit is contained in:
@@ -102,10 +102,12 @@ class UpdateTrigger:
|
||||
# We alert when price moves from below to above (or vice versa)
|
||||
target_price = self._alert.price
|
||||
if self._last_trigger is None:
|
||||
# First time - check if current price crossed the threshold
|
||||
if new_datum[1] >= target_price:
|
||||
# First time - initialize tracking
|
||||
self._last_trigger = new_datum
|
||||
if new_datum[1] >= target_price:
|
||||
# Price already at/above target - alert and squelch
|
||||
self._last_alerting = new_datum
|
||||
self._squelched = True
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
@@ -117,21 +119,21 @@ class UpdateTrigger:
|
||||
crossed_up = old_price < target_price <= new_price
|
||||
crossed_down = old_price >= target_price > new_price
|
||||
|
||||
# Always update last_trigger for tracking
|
||||
self._last_trigger = new_datum
|
||||
|
||||
if crossed_up or crossed_down:
|
||||
self._last_trigger = new_datum
|
||||
self._last_alerting = new_datum
|
||||
was_squelched = self._squelched
|
||||
self._squelched = True
|
||||
return not was_squelched
|
||||
elif self._squelched:
|
||||
# Update last_trigger but don't alert (we're tracking current price)
|
||||
self._last_trigger = new_datum
|
||||
# If we moved away from threshold, allow next crossing to alert
|
||||
if (crossed_up and new_price < target_price) or (crossed_down and new_price >= target_price):
|
||||
# We're crossing the threshold
|
||||
if self._squelched:
|
||||
# Currently squelched - this crossing unsquelches us
|
||||
# but doesn't alert (prevents rapid-fire alerts on oscillation)
|
||||
self._squelched = False
|
||||
return False
|
||||
else:
|
||||
# Just update the last trigger for tracking
|
||||
self._last_trigger = new_datum
|
||||
# Not squelched - send alert and squelch
|
||||
self._last_alerting = new_datum
|
||||
self._squelched = True
|
||||
return True
|
||||
return False
|
||||
case _:
|
||||
time_range = datetime.timedelta(days=int(365.25 * 6))
|
||||
|
||||
@@ -14,6 +14,11 @@ class Alert:
|
||||
def __init__(
|
||||
self, alert: pdb.AlertType, flavor: Flavor, region: Region, price: int = 0
|
||||
) -> None:
|
||||
# Validate price for SPECIFIC_PRICE alerts
|
||||
if alert == AlertType.SPECIFIC_PRICE:
|
||||
if price is None or price <= 0:
|
||||
raise ValueError("SPECIFIC_PRICE alerts require a positive price value")
|
||||
|
||||
# AlertType is the Primary Key
|
||||
self._alert_type: pdb.AlertType = alert
|
||||
# Flavor (Retail, Classic) is the Sort Key
|
||||
|
||||
@@ -226,7 +226,7 @@ class Tracker(Extension):
|
||||
case AlertCategory.CUSTOM:
|
||||
alert_type = AlertType.SPECIFIC_PRICE
|
||||
|
||||
except TimeoutError:
|
||||
except (TimeoutError, ValueError):
|
||||
return
|
||||
|
||||
else:
|
||||
@@ -531,14 +531,16 @@ class Tracker(Extension):
|
||||
price_str = modal_ctx.responses["price_input"]
|
||||
try:
|
||||
price_gold = int(price_str.replace(",", "").replace(" ", "").replace("g", ""))
|
||||
if price_gold <= 0:
|
||||
await modal_ctx.send("Price must be greater than 0", ephemeral=True)
|
||||
# Convert gold to copper (1 gold = 10000 copper)
|
||||
price_copper = price_gold
|
||||
await modal_ctx.send(f"Custom price alert set for {format(price_gold, ',')}g", ephemeral=True)
|
||||
return price_copper
|
||||
except ValueError:
|
||||
await modal_ctx.send("Invalid price. Please enter a valid number.", ephemeral=True)
|
||||
raise
|
||||
|
||||
if price_gold <= 0:
|
||||
await modal_ctx.send("Price must be greater than 0", ephemeral=True)
|
||||
raise ValueError("Price must be greater than 0")
|
||||
|
||||
await modal_ctx.send(f"Custom price alert set for {format(price_gold, ',')}g", ephemeral=True)
|
||||
return price_gold
|
||||
|
||||
async def _user_is_registered(self, ctx: SlashContext) -> bool:
|
||||
if not await self._users.exists(ctx.user.id):
|
||||
|
||||
Reference in New Issue
Block a user