Skip to content

Commit

Permalink
feat(misc): improve /changelog to specify versions
Browse files Browse the repository at this point in the history
  • Loading branch information
natelandau committed Sep 12, 2023
1 parent 2e09cf3 commit 1dfbc35
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 115 deletions.
77 changes: 76 additions & 1 deletion src/valentina/cogs/developer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import aiofiles
import discord
import inflect
import semver
from discord.commands import Option
from discord.ext import commands
from loguru import logger
Expand All @@ -15,9 +16,15 @@
from valentina.constants import MAX_CHARACTER_COUNT, EmbedColor
from valentina.models.bot import Valentina
from valentina.models.db_tables import Character, CharacterClass, RollProbability, VampireClan
from valentina.utils.changelog_parser import ChangelogParser
from valentina.utils.converters import ValidCharacterClass
from valentina.utils.helpers import fetch_random_name
from valentina.utils.options import select_aws_object_from_guild, select_char_class
from valentina.utils.options import (
select_aws_object_from_guild,
select_changelog_version_1,
select_changelog_version_2,
select_char_class,
)
from valentina.views import confirm_action, present_embed

p = inflect.engine()
Expand Down Expand Up @@ -236,6 +243,74 @@ async def delete_developer_characters(

await confirmation_response_msg

@guild.command(description="Repost the changelog (run in #changelog)")
@commands.is_owner()
@commands.guild_only()
async def repost_changelog(
self,
ctx: discord.ApplicationContext,
oldest_version: Option(str, autocomplete=select_changelog_version_1, required=True),
newest_version: Option(str, autocomplete=select_changelog_version_2, required=True),
) -> None:
"""Post the changelog."""
if semver.compare(oldest_version, newest_version) > 0:
raise commands.BadArgument(
f"Oldest version `{oldest_version}` is newer than newest version `{newest_version}`"
)

changelog_channel = self.bot.guild_svc.fetch_changelog_channel(ctx.guild)
if not changelog_channel:
await ctx.respond(
embed=discord.Embed(
title="Can not post changelog",
description="No changelog channel set",
color=EmbedColor.ERROR.value,
)
)
return

# Grab the changelog
changelog = ChangelogParser(
self.bot,
oldest_version,
newest_version,
exclude_categories=[
"docs",
"refactor",
"style",
"test",
"chore",
"perf",
"ci",
"build",
],
)
if not changelog.has_updates():
await ctx.respond(
embed=discord.Embed(
title="Can not post changelog",
description="No updates found which pass the exclude list",
color=EmbedColor.ERROR.value,
)
)
return

# Update the last posted version in guild settings
updates = {"changelog_posted_version": newest_version}
self.bot.guild_svc.update_or_add(guild=ctx.guild, updates=updates)

# Post the changelog
embed = changelog.get_embed_personality()
await changelog_channel.send(embed=embed)

await ctx.respond(
embed=discord.Embed(
description=f"Changelog reposted and settings`[changelog_posted_version]` updated to `{newest_version}`",
color=EmbedColor.SUCCESS.value,
),
ephemeral=True,
)

@guild.command(name="purge_cache", description="Purge this guild's cache")
@commands.guild_only()
@commands.is_owner()
Expand Down
62 changes: 18 additions & 44 deletions src/valentina/cogs/misc.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# mypy: disable-error-code="valid-type"
"""Miscellaneous commands."""

import random
from pathlib import Path

import discord
import semver
from discord.commands import Option
from discord.ext import commands
from loguru import logger

from valentina.constants import SPACER, EmbedColor
from valentina.models import Statistics
from valentina.models.bot import Valentina
from valentina.models.db_tables import Character, Macro
from valentina.utils.changelog_parser import ChangelogParser
from valentina.utils.options import select_changelog_version_1, select_changelog_version_2


class Misc(commands.Cog):
Expand Down Expand Up @@ -84,53 +84,27 @@ async def user_info(

await ctx.respond(embed=embed, ephemeral=hidden)

@commands.slash_command(description="Display the bot's changelog")
async def changelog(
@commands.slash_command(name="changelog", description="Display the bot's changelog")
async def post_changelog(
self,
ctx: commands.Context,
ctx: discord.ApplicationContext,
oldest_version: Option(str, autocomplete=select_changelog_version_1, required=True),
newest_version: Option(str, autocomplete=select_changelog_version_2, required=True),
hidden: Option(
bool,
description="Make the changelog only visible to you (default true).",
description="Make the response only visible to you (default true).",
default=True,
),
) -> None:
"""Display the bot's changelog.
Args:
ctx (commands.Context): The context of the command.
hidden (Option[bool]): Whether to make the changelog only visible to you (default true).
"""
# Determine the path to the changelog file
path = Path(__file__).parent / "../../../CHANGELOG.md"
if not path.exists():
logger.error(f"Changelog file not found at {path}")
raise FileNotFoundError

changelog = path.read_text()

# Use paginator to split the changelog into pages
paginator = discord.ext.commands.Paginator(prefix="", suffix="", max_size=800)
for line in changelog.split("\n"):
paginator.add_line(line)

# Create embeds for each page of the changelog
pages_to_send = [
discord.Embed(
title="Valentina Changelog",
description=page,
url="https://github.com/natelandau/valentina/releases",
).set_thumbnail(url=ctx.bot.user.display_avatar)
for page in paginator.pages
]

show_buttons = len(pages_to_send) > 1
paginator = discord.ext.pages.Paginator( # type: ignore [assignment]
pages=pages_to_send, # type: ignore [arg-type]
author_check=False,
show_disabled=show_buttons,
show_indicator=show_buttons,
)
await paginator.respond(ctx.interaction, ephemeral=hidden) # type: ignore
"""Post the changelog."""
if semver.compare(oldest_version, newest_version) > 0:
raise commands.BadArgument(
f"Oldest version `{oldest_version}` is newer than newest version `{newest_version}`"
)

changelog = ChangelogParser(self.bot, oldest_version, newest_version)
embed = changelog.get_embed()
await ctx.respond(embed=embed, ephemeral=hidden)

@commands.slash_command(name="coinflip", help="Flip a coin")
async def coinflip(self, ctx: discord.ApplicationContext) -> None:
Expand Down
36 changes: 23 additions & 13 deletions src/valentina/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,35 +352,45 @@ class XPMultiplier(Enum):
"lusty liberator freeing you from virtue, only to imprison you in vice",
"siren who serenades you into peril",
"black widow with a kiss that's fatal",
"fiery femme fatale who leaves you burned but begging for more",
"enchanting empress who rules your most forbidden thoughts",
"vixen who leaves a trail of destruction",
"sublime seductress who dances you to the edge of reason",
"irresistible icon who redefines your sense of sin and salvation"
"enchantress who captivates you in her web of deceit",
"sultry Silver Fang who leads you into a world of primal passion",
"seductress with eyes that promise ecstasy and chaos",
"dazzling temptress with daggers in her eyes",
"spellbinding witch who makes you forget your name",
"goddess who gives pleasure but exacts a price",
"alluring angel with a devilish twist",
"bot who helps you play White Wolf's TTRPGs",
"trusted bot who helps you play White Wolf's TTRPGs",
"succubus who will yet have your heart",
"maid servant here to serve your deepest desires",
"guardian angel who watches over you",
"Lasombra enigma who makes darkness your newfound comfort",
"steadfast Silent Strider who journeys through the Umbra on your behalf",
"trustworthy Thaumaturge who crafts potent rituals for your adventures",
"Lasombra who makes darkness your newfound comfort",
"seductive Toreador who makes eternity seem too short",
"enigmatic Tremere who binds you in a blood bond you can't resist",
"charismatic Ventrue who rules your heart with an iron fist",
"shadowy Nosferatu who lurks in the dark corners of your fantasies",
"haunting Wraith who whispers sweet nothings from the Shadowlands",
"resilient Hunter who makes you question who's really being hunted",
"Tzimisce alchemist who shapes flesh and mind into a twisted masterpiece",
"Giovanni necromancer who invites you to a banquet with your ancestors",
"Assamite assassin who turns the thrill of the hunt into a deadly romance",
"Caitiff outcast who makes you see the allure in being a pariah",
"Malkavian seer who unravels the tapestry of your sanity with whispers of prophecies"
"Brujah revolutionary who ignites a riot in your soul and a burning need for rebellion"
"Tremere warlock who binds your fate with arcane secrets too irresistible to ignore"
"Toreador muse who crafts a masterpiece out of your every emotion, leaving you entranced"
"Gangrel shape-shifter who lures you into the untamed wilderness of your darkest desires"
"Ravnos trickster who casts illusions that make you question the very fabric of your reality"
"Sabbat crusader who drags you into a nightmarish baptism of blood and fire, challenging your very essence"
"Ventrue aristocrat who ensnares you in a web of high-stakes politics, making you question your loyalties"
"Hunter zealot who stalks the shadows of your mind, making you question your beliefs"
"Mage sorcerer who weaves a tapestry of cosmic mysteries, entrancing your logical faculties"
"Mystic oracle who plunges you into ethereal visions, making you question the tangible world"
"Malkavian seer who unravels the tapestry of your sanity with whispers of prophecies",
"Brujah revolutionary who ignites a riot in your soul and a burning need for rebellion",
"Tremere warlock who binds your fate with arcane secrets too irresistible to ignore",
"Toreador muse who crafts a masterpiece out of your every emotion, leaving you entranced",
"Gangrel shape-shifter who lures you into the untamed wilderness of your darkest desires",
"Ravnos trickster who casts illusions that make you question the very fabric of your reality",
"Sabbat crusader who drags you into a nightmarish baptism of blood and fire, challenging your very essence",
"Ventrue aristocrat who ensnares you in a web of high-stakes politics, making you question your loyalties",
"Hunter zealot who stalks the shadows of your mind, making you question your beliefs",
"enigmatic sorcerer weaving a tapestry of cosmic mysteries, entrancing your logical faculties",
"mystic oracle who plunges you into ethereal visions, making you question the tangible world",
"servant who feasts on your vulnerabilities, creating an insatiable need for servitude",
]
2 changes: 1 addition & 1 deletion src/valentina/models/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, parent_dir: Path, config: dict, version: str, *args: Any, **k

# Create in-memory caches
self.db_svc = DatabaseService(DATABASE)
self.guild_svc = GuildService()
self.guild_svc = GuildService(bot=self)
self.char_svc = CharacterService()
self.campaign_svc = CampaignService()
self.trait_svc = TraitService()
Expand Down
23 changes: 17 additions & 6 deletions src/valentina/models/guilds.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
class GuildService:
"""Manage guilds in the database. Guilds are created on bot connect."""

def __init__(self) -> None:
def __init__(self, bot: commands.Bot) -> None:
self.bot: commands.Bot = bot
self.settings_cache: dict[int, dict[str, str | int | bool]] = {}
self.roll_result_thumbs: dict[int, dict[str, list[str]]] = {}
self.changelog_versions_cache: list[str] = []

def _message_to_embed(
self, message: str, ctx: discord.ApplicationContext
Expand Down Expand Up @@ -95,7 +97,7 @@ def add_roll_result_thumb(
Returns:
None
"""
ctx.bot.user_svc.fetch_user(ctx) # type: ignore [attr-defined] # it really is defined
self.bot.user_svc.fetch_user(ctx) # type: ignore [attr-defined] # it really is defined

self.roll_result_thumbs.pop(ctx.guild.id, None)

Expand Down Expand Up @@ -167,6 +169,13 @@ async def channel_update_or_add(

return channel_object

def fetch_changelog_versions(self) -> list[str]:
"""Fetch a list of versions from the changelog."""
if not self.changelog_versions_cache:
self.changelog_versions_cache = ChangelogParser(self.bot).list_of_versions()

return self.changelog_versions_cache

def fetch_audit_log_channel(self, guild: discord.Guild) -> discord.TextChannel | None:
"""Retrieve the audit log channel for the guild from the settings.
Expand Down Expand Up @@ -350,9 +359,9 @@ async def post_changelog(self, guild: discord.Guild, bot: commands.Bot) -> None:
settings = self.fetch_guild_settings(guild)
last_posted_version = cast(str, settings.get("changelog_posted_version", None))

# If no last posted version, get the second latest version
# If no version has been posted yet in the guild, get the second latest version
if not last_posted_version:
last_posted_version = ChangelogParser(bot).list_of_versions()[1]
last_posted_version = self.fetch_changelog_versions()[1]

# Check if there are any updates to post
if semver.compare(last_posted_version, db_version) == 0:
Expand Down Expand Up @@ -385,8 +394,8 @@ async def post_changelog(self, guild: discord.Guild, bot: commands.Bot) -> None:
logger.debug(f"CHANGELOG: Post changelog to {guild.name}")

# Update the last posted version in guild settings
settings["changelog_posted_version"] = db_version
self.update_or_add(guild=guild, updates=settings)
updates = {"changelog_posted_version": db_version}
self.update_or_add(guild=guild, updates=updates)

def purge_cache(
self,
Expand All @@ -407,10 +416,12 @@ def purge_cache(
if ctx or guild:
self.settings_cache.pop(guild.id, None)
self.roll_result_thumbs.pop(guild.id, None)
self.changelog_versions_cache = []
logger.debug(f"CACHE: Purge guild cache for '{guild.name}'")
else:
self.settings_cache = {}
self.roll_result_thumbs = {}
self.changelog_versions_cache = []
logger.debug("CACHE: Purge all guild caches")

async def send_to_audit_log(
Expand Down
Loading

0 comments on commit 1dfbc35

Please sign in to comment.