Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions src/gw2/cogs/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ async def session(ctx):
async with ctx.message.channel.typing():
color = ctx.bot.settings["gw2"]["EmbedColor"]

# Use DB timestamps for wall-clock session duration
start_time = rs_session[0]["created_at"]
end_time = rs_session[0]["updated_at"]
# Use JSONB date fields for session duration
start_time = bot_utils.convert_str_to_datetime_short(rs_start["date"])
end_time = bot_utils.convert_str_to_datetime_short(rs_end["date"])

time_passed = gw2_utils.get_time_passed(start_time, end_time)
player_wait_minutes = 1
Expand All @@ -119,7 +119,7 @@ async def session(ctx):
)

acc_name = rs_session[0]["acc_name"]
session_date = str(start_time).split()[0]
session_date = rs_start["date"].split()[0]
embed = discord.Embed(color=color)
embed.set_author(
name=f"{ctx.message.author.display_name}'s {gw2_messages.SESSION_TITLE} ({session_date})",
Expand All @@ -128,12 +128,8 @@ async def session(ctx):
embed.add_field(name=gw2_messages.ACCOUNT_NAME, value=chat_formatting.inline(acc_name))
embed.add_field(name=gw2_messages.SERVER, value=chat_formatting.inline(gw2_server))

# Play time from API age (actual in-game time)
play_time_seconds = rs_end["age"] - rs_start["age"]
if play_time_seconds > 0:
play_time_str = gw2_utils.format_seconds_to_time(play_time_seconds)
else:
play_time_str = str(time_passed.timedelta)
# Play time from DB timestamps (session duration)
play_time_str = gw2_utils.format_seconds_to_time(int(time_passed.timedelta.total_seconds()))
embed.add_field(name=gw2_messages.PLAY_TIME, value=chat_formatting.inline(play_time_str))

# Gold (special formatting)
Expand All @@ -152,6 +148,11 @@ async def session(ctx):
# All wallet currencies (except gold, handled above)
_add_wallet_currency_fields(embed, rs_start, rs_end)

embed.set_footer(
icon_url=ctx.bot.user.avatar.url if ctx.bot.user.avatar else None,
text=f"{bot_utils.get_current_date_time_str_long()} UTC",
)

if (
not (isinstance(ctx.channel, discord.DMChannel))
and hasattr(ctx.message.author, "activity")
Expand Down
48 changes: 17 additions & 31 deletions tests/unit/gw2/cogs/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import discord
import pytest
from datetime import datetime
from datetime import datetime, timedelta
from src.gw2.cogs.sessions import (
GW2Session,
_add_deaths_field,
Expand Down Expand Up @@ -48,6 +48,7 @@ def test_gw2_session_inheritance(self, gw2_session_cog):
def _make_session_data(start_overrides=None, end_overrides=None):
"""Helper to create session data with defaults."""
base_stats = {
"date": "2024-01-15 10:00:00",
"age": 5000000,
"gold": 100000,
"karma": 50000,
Expand All @@ -71,8 +72,9 @@ def _make_session_data(start_overrides=None, end_overrides=None):
"gems": 0,
}
end_stats = {
"date": "2024-01-15 12:30:00",
"age": 5009000,
**{k: v for k, v in base_stats.items() if k != "age"},
**{k: v for k, v in base_stats.items() if k not in ("date", "age")},
}
if start_overrides:
base_stats.update(start_overrides)
Expand Down Expand Up @@ -163,7 +165,7 @@ def sample_time_passed(self):
time_obj.minutes = 30
time_obj.seconds = 0
time_obj.days = 0
time_obj.timedelta = "2:30:00"
time_obj.timedelta = timedelta(hours=2, minutes=30)
return time_obj

def _run_session(self, mock_ctx, sample_api_key_data, session_data, sample_time_passed, extra_patches=None):
Expand All @@ -183,6 +185,7 @@ async def run(self_runner):
patch("src.gw2.cogs.sessions.Gw2KeyDal") as mock_dal,
patch("src.gw2.cogs.sessions.Gw2ConfigsDal") as mock_configs,
patch("src.gw2.cogs.sessions.Gw2SessionsDal") as mock_sessions_dal,
patch("src.gw2.cogs.sessions.bot_utils.convert_str_to_datetime_short", side_effect=lambda x: x),
patch("src.gw2.cogs.sessions.gw2_utils.get_time_passed", return_value=sample_time_passed),
patch("src.gw2.cogs.sessions.Gw2SessionCharsDal") as mock_chars_dal_class,
patch("src.gw2.cogs.sessions.bot_utils.send_paginated_embed") as mock_send,
Expand Down Expand Up @@ -326,22 +329,20 @@ async def test_session_time_passed_less_than_one_minute(self, mock_ctx, sample_a
mock_configs.return_value.get_gw2_server_configs = AsyncMock(return_value=[{"session": True}])
with patch("src.gw2.cogs.sessions.Gw2SessionsDal") as mock_sessions_dal:
mock_sessions_dal.return_value.get_user_last_session = AsyncMock(return_value=session_data)
with patch("src.gw2.cogs.sessions.gw2_utils.get_time_passed", return_value=time_obj):
with patch("src.gw2.cogs.sessions.gw2_utils.send_msg") as mock_send_msg:
await session(mock_ctx)
mock_send_msg.assert_called_once()
msg = mock_send_msg.call_args[0][1]
assert "still updating" in msg.lower() or "Bot still updating" in msg
with patch("src.gw2.cogs.sessions.bot_utils.convert_str_to_datetime_short", side_effect=lambda x: x):
with patch("src.gw2.cogs.sessions.gw2_utils.get_time_passed", return_value=time_obj):
with patch("src.gw2.cogs.sessions.gw2_utils.send_msg") as mock_send_msg:
await session(mock_ctx)
mock_send_msg.assert_called_once()
msg = mock_send_msg.call_args[0][1]
assert "still updating" in msg.lower() or "Bot still updating" in msg

# === Playtime tests ===

@pytest.mark.asyncio
async def test_session_play_time_from_api_age(self, mock_ctx, sample_api_key_data, sample_time_passed):
"""Test that play time uses API age difference when available."""
session_data = _make_session_data(
start_overrides={"age": 5000000},
end_overrides={"age": 5009000},
)
async def test_session_play_time_from_jsonb_dates(self, mock_ctx, sample_api_key_data, sample_time_passed):
"""Test that play time uses JSONB date fields for session duration."""
session_data = _make_session_data()
runner = self._run_session(mock_ctx, sample_api_key_data, session_data, sample_time_passed)
async with runner.run() as r:
await session(mock_ctx)
Expand All @@ -350,21 +351,6 @@ async def test_session_play_time_from_api_age(self, mock_ctx, sample_api_key_dat
assert play_time_field is not None
assert "2h 30m" in play_time_field.value

@pytest.mark.asyncio
async def test_session_play_time_fallback_when_zero_age(self, mock_ctx, sample_api_key_data, sample_time_passed):
"""Test that play time falls back to timedelta when age diff is 0."""
session_data = _make_session_data(
start_overrides={"age": 5000000},
end_overrides={"age": 5000000},
)
runner = self._run_session(mock_ctx, sample_api_key_data, session_data, sample_time_passed)
async with runner.run() as r:
await session(mock_ctx)
embed = r.mock_send.call_args[0][1]
play_time_field = next((f for f in embed.fields if f.name == "Play time"), None)
assert play_time_field is not None
assert "2:30:00" in play_time_field.value

# === Gold tests ===

@pytest.mark.asyncio
Expand Down Expand Up @@ -807,7 +793,7 @@ async def test_session_time_passed_exactly_one_minute(self, mock_ctx, sample_api
time_obj.hours = 0
time_obj.minutes = 1
time_obj.seconds = 0
time_obj.timedelta = "0:01:00"
time_obj.timedelta = timedelta(minutes=1)

runner = self._run_session(mock_ctx, sample_api_key_data, session_data, time_obj)
async with runner.run() as r:
Expand Down