feat: limit scouting to Standard/Premium packs, simplify scout view
- Add SCOUTABLE_PACK_TYPES env var (default: Standard,Premium) to control
which pack types offer scout opportunities
- Unify embed construction into build_scout_embed() — removes 3 near-duplicate
embed builders across scout_view.py and scouting.py
- Replace manual total_scouts counter with derived property from claims dict
- Remove redundant db_get("current") API call per scout click — use PD_SEASON
- Remove duplicate expiry computation in create_scout_opportunity
- Move send_to_channel to top-level import, remove redundant local import
- Update tests to match simplified code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0432f9d3f4
commit
1b83be89bb
@ -11,15 +11,15 @@ import logging
|
||||
|
||||
import discord
|
||||
|
||||
from api_calls import db_get, db_post
|
||||
from api_calls import db_post
|
||||
from helpers.main import get_team_by_owner, get_card_embeds
|
||||
from helpers.scouting import (
|
||||
SCOUT_TOKENS_PER_DAY,
|
||||
build_scouted_card_list,
|
||||
build_scout_embed,
|
||||
get_scout_tokens_used,
|
||||
)
|
||||
from helpers.utils import int_timestamp
|
||||
from helpers.discord_utils import get_team_embed
|
||||
from helpers.discord_utils import get_team_embed, send_to_channel
|
||||
from helpers.constants import IMAGES, PD_SEASON
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
@ -60,8 +60,6 @@ class ScoutView(discord.ui.View):
|
||||
self.scouted_users: set[int] = set()
|
||||
# Users currently being processed (prevent double-click race)
|
||||
self.processing_users: set[int] = set()
|
||||
# Total scout count
|
||||
self.total_scouts = 0
|
||||
|
||||
for i, card in enumerate(cards):
|
||||
button = ScoutButton(
|
||||
@ -71,30 +69,21 @@ class ScoutView(discord.ui.View):
|
||||
)
|
||||
self.add_item(button)
|
||||
|
||||
@property
|
||||
def total_scouts(self) -> int:
|
||||
return sum(len(v) for v in self.claims.values())
|
||||
|
||||
async def update_message(self):
|
||||
"""Refresh the embed with current claim state."""
|
||||
if not self.message:
|
||||
return
|
||||
|
||||
card_list = build_scouted_card_list(self.card_lines, self.claims)
|
||||
|
||||
title = f"Scout Opportunity! ({self.total_scouts} scouted)"
|
||||
embed = get_team_embed(title=title, team=self.opener_team)
|
||||
if self.expires_unix:
|
||||
time_line = f"Scout window closes <t:{self.expires_unix}:R>."
|
||||
else:
|
||||
time_line = "Scout window closes in **30 minutes**."
|
||||
|
||||
embed.description = (
|
||||
f"**{self.opener_team['lname']}**'s pack\n\n"
|
||||
f"{card_list}\n\n"
|
||||
f"Pick a card — but which is which?\n"
|
||||
f"Costs 1 Scout Token (2 per day, resets at midnight Central).\n"
|
||||
f"{time_line}"
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"Paper Dynasty Season {PD_SEASON} \u2022 One scout per player",
|
||||
icon_url=IMAGES["logo"],
|
||||
embed, _ = build_scout_embed(
|
||||
self.opener_team,
|
||||
card_lines=self.card_lines,
|
||||
expires_unix=self.expires_unix,
|
||||
claims=self.claims,
|
||||
total_scouts=self.total_scouts,
|
||||
)
|
||||
|
||||
try:
|
||||
@ -109,22 +98,12 @@ class ScoutView(discord.ui.View):
|
||||
|
||||
if self.message:
|
||||
try:
|
||||
from helpers.scouting import build_scouted_card_list
|
||||
|
||||
card_list = build_scouted_card_list(self.card_lines, self.claims)
|
||||
|
||||
if self.total_scouts > 0:
|
||||
title = f"Scout Window Closed ({self.total_scouts} scouted)"
|
||||
else:
|
||||
title = "Scout Window Closed"
|
||||
|
||||
embed = get_team_embed(title=title, team=self.opener_team)
|
||||
embed.description = (
|
||||
f"**{self.opener_team['lname']}**'s pack\n\n" f"{card_list}"
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"Paper Dynasty Season {PD_SEASON}",
|
||||
icon_url=IMAGES["logo"],
|
||||
embed, _ = build_scout_embed(
|
||||
self.opener_team,
|
||||
card_lines=self.card_lines,
|
||||
claims=self.claims,
|
||||
total_scouts=self.total_scouts,
|
||||
closed=True,
|
||||
)
|
||||
await self.message.edit(embed=embed, view=self)
|
||||
except Exception as e:
|
||||
@ -228,14 +207,12 @@ class ScoutButton(discord.ui.Button):
|
||||
)
|
||||
|
||||
# Consume a scout token
|
||||
current = await db_get("current")
|
||||
await db_post(
|
||||
"rewards",
|
||||
payload={
|
||||
"name": "Scout Token",
|
||||
"team_id": scouter_team["id"],
|
||||
"season": current["season"] if current else PD_SEASON,
|
||||
"week": current["week"] if current else 1,
|
||||
"season": PD_SEASON,
|
||||
"created": int_timestamp(),
|
||||
},
|
||||
)
|
||||
@ -246,7 +223,6 @@ class ScoutButton(discord.ui.Button):
|
||||
view.claims[player_id] = []
|
||||
view.claims[player_id].append(scouter_team["lname"])
|
||||
view.scouted_users.add(interaction.user.id)
|
||||
view.total_scouts += 1
|
||||
|
||||
# Update the shared embed
|
||||
await view.update_message()
|
||||
@ -269,8 +245,6 @@ class ScoutButton(discord.ui.Button):
|
||||
# Notify for shiny scouts (rarity >= 5)
|
||||
if self.card["player"]["rarity"]["value"] >= 5:
|
||||
try:
|
||||
from helpers.discord_utils import send_to_channel
|
||||
|
||||
notif_embed = get_team_embed(title="Rare Scout!", team=scouter_team)
|
||||
notif_embed.description = (
|
||||
f"**{scouter_team['lname']}** scouted a "
|
||||
|
||||
@ -1770,15 +1770,17 @@ async def open_st_pr_packs(all_packs: list, team: dict, context):
|
||||
await context.channel.send(content=f"Let's head down to {pack_channel.mention}!")
|
||||
await display_cards(all_cards, team, pack_channel, author, pack_cover=pack_cover)
|
||||
|
||||
# Create scout opportunities for each pack
|
||||
from helpers.scouting import create_scout_opportunity
|
||||
# Create scout opportunities for each pack (Standard/Premium only)
|
||||
from helpers.scouting import create_scout_opportunity, SCOUTABLE_PACK_TYPES
|
||||
|
||||
for p_id in pack_ids:
|
||||
pack_cards = [c for c in all_cards if c.get("pack_id") == p_id]
|
||||
if pack_cards:
|
||||
await create_scout_opportunity(
|
||||
pack_cards, team, pack_channel, author, context
|
||||
)
|
||||
pack_type_name = all_packs[0].get("pack_type", {}).get("name")
|
||||
if pack_type_name in SCOUTABLE_PACK_TYPES:
|
||||
for p_id in pack_ids:
|
||||
pack_cards = [c for c in all_cards if c.get("pack_id") == p_id]
|
||||
if pack_cards:
|
||||
await create_scout_opportunity(
|
||||
pack_cards, team, pack_channel, author, context
|
||||
)
|
||||
if len(pack_ids) > 1:
|
||||
await asyncio.sleep(2)
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ and embed formatting for the scouting feature.
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
|
||||
import discord
|
||||
@ -20,6 +21,8 @@ logger = logging.getLogger("discord_app")
|
||||
|
||||
SCOUT_TOKENS_PER_DAY = 2
|
||||
SCOUT_WINDOW_SECONDS = 1800 # 30 minutes
|
||||
_scoutable_raw = os.environ.get("SCOUTABLE_PACK_TYPES", "Standard,Premium")
|
||||
SCOUTABLE_PACK_TYPES = {s.strip() for s in _scoutable_raw.split(",") if s.strip()}
|
||||
|
||||
# Rarity value → display symbol
|
||||
RARITY_SYMBOLS = {
|
||||
@ -71,39 +74,70 @@ def _build_card_lines(cards: list[dict]) -> list[tuple[int, str]]:
|
||||
|
||||
def build_scout_embed(
|
||||
opener_team: dict,
|
||||
cards: list[dict],
|
||||
cards: list[dict] = None,
|
||||
card_lines: list[tuple[int, str]] = None,
|
||||
expires_unix: int = None,
|
||||
claims: dict[int, list[str]] = None,
|
||||
total_scouts: int = 0,
|
||||
closed: bool = False,
|
||||
) -> tuple[discord.Embed, list[tuple[int, str]]]:
|
||||
"""Build the embed shown above the scout buttons.
|
||||
|
||||
Shows a shuffled list of cards (rarity + player name) so scouters
|
||||
know what's in the pack but not which button maps to which card.
|
||||
Returns (embed, card_lines) so the view can store the shuffled order.
|
||||
"""
|
||||
embed = get_team_embed(title="Scout Opportunity!", team=opener_team)
|
||||
|
||||
if card_lines is None:
|
||||
Parameters
|
||||
----------
|
||||
closed : if True, renders the "Scout Window Closed" variant
|
||||
claims : scouted card tracking dict for build_scouted_card_list
|
||||
total_scouts : number of scouts so far (for title display)
|
||||
"""
|
||||
if card_lines is None and cards is not None:
|
||||
card_lines = _build_card_lines(cards)
|
||||
|
||||
card_list = "\n".join(line for _, line in card_lines)
|
||||
|
||||
if expires_unix:
|
||||
time_line = f"Scout window closes <t:{expires_unix}:R>."
|
||||
if claims and card_lines:
|
||||
card_list = build_scouted_card_list(card_lines, claims)
|
||||
elif card_lines:
|
||||
card_list = "\n".join(line for _, line in card_lines)
|
||||
else:
|
||||
time_line = "Scout window closes in **30 minutes**."
|
||||
card_list = ""
|
||||
|
||||
embed.description = (
|
||||
f"**{opener_team['lname']}** just opened a pack!\n\n"
|
||||
f"**Cards in this pack:**\n{card_list}\n\n"
|
||||
f"Pick a card — but which is which?\n"
|
||||
f"Costs 1 Scout Token (2 per day, resets at midnight Central).\n"
|
||||
f"{time_line}"
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"Paper Dynasty Season {PD_SEASON} \u2022 One scout per player",
|
||||
icon_url=IMAGES["logo"],
|
||||
)
|
||||
if closed:
|
||||
if total_scouts > 0:
|
||||
title = f"Scout Window Closed ({total_scouts} scouted)"
|
||||
else:
|
||||
title = "Scout Window Closed"
|
||||
elif total_scouts > 0:
|
||||
title = f"Scout Opportunity! ({total_scouts} scouted)"
|
||||
else:
|
||||
title = "Scout Opportunity!"
|
||||
|
||||
embed = get_team_embed(title=title, team=opener_team)
|
||||
|
||||
if closed:
|
||||
embed.description = f"**{opener_team['lname']}**'s pack\n\n" f"{card_list}"
|
||||
embed.set_footer(
|
||||
text=f"Paper Dynasty Season {PD_SEASON}",
|
||||
icon_url=IMAGES["logo"],
|
||||
)
|
||||
else:
|
||||
if expires_unix:
|
||||
time_line = f"Scout window closes <t:{expires_unix}:R>."
|
||||
else:
|
||||
time_line = "Scout window closes in **30 minutes**."
|
||||
|
||||
embed.description = (
|
||||
f"**{opener_team['lname']}**'s pack\n\n"
|
||||
f"{card_list}\n\n"
|
||||
f"Pick a card — but which is which?\n"
|
||||
f"Costs 1 Scout Token (2 per day, resets at midnight Central).\n"
|
||||
f"{time_line}"
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"Paper Dynasty Season {PD_SEASON} \u2022 One scout per player",
|
||||
icon_url=IMAGES["logo"],
|
||||
)
|
||||
return embed, card_lines
|
||||
|
||||
|
||||
@ -163,7 +197,9 @@ async def create_scout_opportunity(
|
||||
return
|
||||
|
||||
now = datetime.datetime.now()
|
||||
expires_at = int_timestamp(now + datetime.timedelta(seconds=SCOUT_WINDOW_SECONDS))
|
||||
expires_dt = now + datetime.timedelta(seconds=SCOUT_WINDOW_SECONDS)
|
||||
expires_at = int_timestamp(expires_dt)
|
||||
expires_unix = int(expires_dt.timestamp())
|
||||
created = int_timestamp(now)
|
||||
|
||||
card_ids = [c["id"] for c in pack_cards]
|
||||
@ -183,9 +219,6 @@ async def create_scout_opportunity(
|
||||
logger.error(f"Failed to create scout opportunity: {e}")
|
||||
return
|
||||
|
||||
expires_unix = int(
|
||||
(now + datetime.timedelta(seconds=SCOUT_WINDOW_SECONDS)).timestamp()
|
||||
)
|
||||
embed, card_lines = build_scout_embed(
|
||||
opener_team, pack_cards, expires_unix=expires_unix
|
||||
)
|
||||
|
||||
@ -210,14 +210,12 @@ class TestScoutButtonSuccess:
|
||||
@pytest.mark.asyncio
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_successful_scout_creates_card_copy(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
sample_cards,
|
||||
@ -230,7 +228,6 @@ class TestScoutButtonSuccess:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -369,14 +366,12 @@ class TestMultiScout:
|
||||
@pytest.mark.asyncio
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_two_users_can_scout_same_card(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
sample_cards,
|
||||
@ -388,7 +383,6 @@ class TestMultiScout:
|
||||
"""Two different users should both be able to scout the same card."""
|
||||
view = self._make_view_with_message(sample_cards, opener_team, mock_bot)
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -430,14 +424,12 @@ class TestMultiScout:
|
||||
@pytest.mark.asyncio
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_same_user_cannot_scout_twice(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
sample_cards,
|
||||
@ -449,7 +441,6 @@ class TestMultiScout:
|
||||
view = self._make_view_with_message(sample_cards, opener_team, mock_bot)
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -579,7 +570,9 @@ class TestScoutViewTimeout:
|
||||
view.card_lines = [
|
||||
(c["player"]["player_id"], f"Line {i}") for i, c in enumerate(sample_cards)
|
||||
]
|
||||
view.total_scouts = 5
|
||||
# Set up claims so total_scouts property returns 5
|
||||
pid = sample_cards[0]["player"]["player_id"]
|
||||
view.claims[pid] = ["Team A", "Team B", "Team C", "Team D", "Team E"]
|
||||
view.message = AsyncMock(spec=discord.Message)
|
||||
view.message.edit = AsyncMock()
|
||||
|
||||
@ -617,14 +610,12 @@ class TestProcessingUserCleanup:
|
||||
@pytest.mark.asyncio
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_processing_cleared_on_success(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
sample_cards,
|
||||
@ -648,7 +639,6 @@ class TestProcessingUserCleanup:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -744,24 +734,22 @@ class TestProcessingUserCleanup:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# db_get("current") fallback
|
||||
# Rewards use PD_SEASON constant
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestCurrentSeasonFallback:
|
||||
"""Tests for the fallback when db_get('current') returns None."""
|
||||
class TestRewardsSeason:
|
||||
"""Tests that reward records always use the PD_SEASON constant."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_current_returns_none_uses_fallback(
|
||||
async def test_rewards_use_pd_season(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
sample_cards,
|
||||
@ -769,7 +757,7 @@ class TestCurrentSeasonFallback:
|
||||
scouter_team,
|
||||
mock_bot,
|
||||
):
|
||||
"""When db_get('current') returns None, rewards should use PD_SEASON fallback."""
|
||||
"""Reward records should always use the PD_SEASON constant for season."""
|
||||
view = ScoutView(
|
||||
scout_opp_id=1,
|
||||
cards=sample_cards,
|
||||
@ -785,7 +773,6 @@ class TestCurrentSeasonFallback:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = None # db_get("current") returns None
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -803,14 +790,13 @@ class TestCurrentSeasonFallback:
|
||||
assert view.total_scouts == 1
|
||||
assert 12345 in view.scouted_users
|
||||
|
||||
# Verify the rewards POST used fallback values
|
||||
# Verify the rewards POST uses PD_SEASON
|
||||
# Order: scout_claims (0), cards (1), rewards (2)
|
||||
from helpers.constants import PD_SEASON
|
||||
|
||||
reward_call = mock_db_post.call_args_list[2]
|
||||
assert reward_call[0][0] == "rewards"
|
||||
assert reward_call[1]["payload"]["season"] == PD_SEASON
|
||||
assert reward_call[1]["payload"]["week"] == 1
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@ -822,17 +808,15 @@ class TestShinyScoutNotification:
|
||||
"""Tests for the rare-card notification path (rarity >= 5)."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("helpers.discord_utils.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_shiny_card_sends_notification(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
mock_send_to_channel,
|
||||
@ -857,7 +841,6 @@ class TestShinyScoutNotification:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -877,17 +860,15 @@ class TestShinyScoutNotification:
|
||||
assert call_args[0][1] == "pd-network-news"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("helpers.discord_utils.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_non_shiny_card_no_notification(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
mock_send_to_channel,
|
||||
@ -912,7 +893,6 @@ class TestShinyScoutNotification:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
|
||||
@ -930,17 +910,15 @@ class TestShinyScoutNotification:
|
||||
mock_send_to_channel.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("helpers.discord_utils.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.send_to_channel", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_card_embeds", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_post", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.db_get", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_scout_tokens_used", new_callable=AsyncMock)
|
||||
@patch("discord_ui.scout_view.get_team_by_owner", new_callable=AsyncMock)
|
||||
async def test_shiny_notification_failure_does_not_crash(
|
||||
self,
|
||||
mock_get_team,
|
||||
mock_get_tokens,
|
||||
mock_db_get,
|
||||
mock_db_post,
|
||||
mock_card_embeds,
|
||||
mock_send_to_channel,
|
||||
@ -965,7 +943,6 @@ class TestShinyScoutNotification:
|
||||
|
||||
mock_get_team.return_value = scouter_team
|
||||
mock_get_tokens.return_value = 0
|
||||
mock_db_get.return_value = {"season": 4, "week": 1} # db_get("current")
|
||||
mock_db_post.return_value = {"id": 100}
|
||||
mock_card_embeds.return_value = [Mock(spec=discord.Embed)]
|
||||
mock_send_to_channel.side_effect = Exception("Channel not found")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user