10 Commits
Author SHA1 Message Date
renovate-bot bb5889f7ae Update ghcr.io/astral-sh/uv Docker tag to v0.6.17
build_latest / build (push) Successful in 22s
2025-04-27 04:03:17 +00:00
renovate-bot 3c489c83e2 Update python Docker tag to v3.13.3 2025-04-13 14:14:54 +00:00
renovate-bot aeb00a107f Update ghcr.io/astral-sh/uv Docker tag to v0.6.14 2025-04-13 14:14:50 +00:00
renovate-bot c65acb094a Update ghcr.io/astral-sh/uv Docker tag to v0.6.12
build_latest / build (push) Successful in 22s
2025-04-06 04:03:39 +00:00
renovate-bot 631c42ac0b Update ghcr.io/astral-sh/uv Docker tag to v0.6.10
build_latest / build (push) Successful in 21s
2025-03-30 04:03:31 +00:00
imcompiling 7811abc33e Merge pull request 'Update actions/checkout action to v4' (#2) from renovate/actions-checkout-4.x into main
build_latest / build (push) Successful in 20s
Reviewed-on: #2
Reviewed-by: imcompiling <[email protected]>
2025-03-23 23:39:22 -04:00
imcompiling 2a01cf09ec Merge pull request 'Update python Docker tag to v3.13.2' (#1) from renovate/python-3.x into main
build_latest / build (push) Has been cancelled
Reviewed-on: #1
Reviewed-by: imcompiling <[email protected]>
2025-03-23 23:39:11 -04:00
renovate-bot 6d9325c354 Update actions/checkout action to v4 2025-03-23 04:03:22 +00:00
renovate-bot 865802eeeb Update python Docker tag to v3.13.2 2025-03-23 04:03:20 +00:00
renovate-bot 8fce10d9be Update ghcr.io/astral-sh/uv Docker tag to v0.6.9
build_latest / build (push) Successful in 22s
2025-03-23 04:03:16 +00:00
12 changed files with 8 additions and 241 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Docker - name: Install Docker
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Docker - name: Install Docker
+2 -8
View File
@@ -4,11 +4,5 @@
"reportArgumentType": "information", "reportArgumentType": "information",
"reportAttributeAccessIssue": "warning" "reportAttributeAccessIssue": "warning"
}, },
"cSpell.words": [ "cSpell.words": ["cakeday", "cakedays", "cooldown", "nextcord"]
"blurple", }
"cakeday",
"cakedays",
"cooldown",
"nextcord"
]
}
+2 -2
View File
@@ -1,7 +1,7 @@
FROM python:3.12.3-slim FROM python:3.13.3-slim
# install uv # install uv
COPY --from=ghcr.io/astral-sh/uv:0.6.5 /uv /uvx /bin/ COPY --from=ghcr.io/astral-sh/uv:0.6.17 /uv /uvx /bin/
COPY . /home COPY . /home
-3
View File
@@ -7,8 +7,6 @@ import pathlib
import nextcord import nextcord
from nextcord.ext import commands from nextcord.ext import commands
from off_cooldown_bot.open_raid import OpenRaid
from .logger import ocd_logger from .logger import ocd_logger
from .settings import settings from .settings import settings
@@ -42,7 +40,6 @@ def run() -> None:
if bot.user is None: if bot.user is None:
ocd_logger.critical("Discord connection failed.") ocd_logger.critical("Discord connection failed.")
return return
bot.add_view(OpenRaid())
ocd_logger.info("%s has connected to Discord!", bot.user.name) ocd_logger.info("%s has connected to Discord!", bot.user.name)
# Run Discord bot # Run Discord bot
@@ -2,8 +2,6 @@
from nextcord.ext import commands from nextcord.ext import commands
from off_cooldown_bot.cogs.commands.test import TestCog
from .birthday import BirthdayCog from .birthday import BirthdayCog
@@ -12,4 +10,3 @@ from .birthday import BirthdayCog
def setup(bot: commands.Bot) -> None: def setup(bot: commands.Bot) -> None:
"""Add all command classes to bot.""" """Add all command classes to bot."""
bot.add_cog(BirthdayCog()) bot.add_cog(BirthdayCog())
bot.add_cog(TestCog(bot))
+1 -2
View File
@@ -10,13 +10,12 @@ from sqlmodel import Session, col, select
from off_cooldown_bot.app import birthday_list from off_cooldown_bot.app import birthday_list
from off_cooldown_bot.database.db import engine from off_cooldown_bot.database.db import engine
from off_cooldown_bot.database.models import UserBirthday from off_cooldown_bot.database.models import UserBirthday
from off_cooldown_bot.utils import GUILDS
class BirthdayCog(commands.Cog, name="Birthday Commands"): class BirthdayCog(commands.Cog, name="Birthday Commands"):
"""Class holds birthday commands.""" """Class holds birthday commands."""
@nextcord.slash_command(guild_ids=GUILDS) @nextcord.slash_command(guild_ids=[1000247361639030804, 822199658306076672])
async def birthday(self, interaction: nextcord.Interaction) -> None: async def birthday(self, interaction: nextcord.Interaction) -> None:
"""Parent slash command for birthday. Never called.""" """Parent slash command for birthday. Never called."""
-43
View File
@@ -1,43 +0,0 @@
"""Commands for testing."""
import nextcord
from nextcord.ext import application_checks, commands
from off_cooldown_bot.open_raid import OpenRaid, build_raid_embed
from off_cooldown_bot.utils import GUILDS
ME = 206602713511886849
def is_me(): # noqa: ANN201
"""Predicate that makes sure only I can run the test commands."""
def predicate(interaction: nextcord.Interaction) -> bool:
if interaction.user is None:
return False
return interaction.user.id == ME
return application_checks.check(predicate)
class TestCog(commands.Cog, name="Test commands."):
"""Class holds commands for testing."""
def __init__(self, bot: commands.Bot) -> None:
self.bot: commands.Bot = bot
@nextcord.slash_command(guild_ids=GUILDS)
async def test(self, interaction: nextcord.Interaction) -> None:
"""Parent slash command for help. Never called."""
@test.subcommand()
@is_me()
async def open_raid(self, interaction: nextcord.Interaction) -> None:
"""
Force starts election.
Args:
interaction (nextcord.Interaction): Interaction with the message.
"""
await interaction.response.send_message("Starting an open raid.", embed=build_raid_embed(), view=OpenRaid())
+1 -23
View File
@@ -13,7 +13,6 @@ from off_cooldown_bot.app import birthday_list
from off_cooldown_bot.database.db import engine from off_cooldown_bot.database.db import engine
from off_cooldown_bot.database.models import UserBirthday from off_cooldown_bot.database.models import UserBirthday
from off_cooldown_bot.logger import ocd_logger from off_cooldown_bot.logger import ocd_logger
from off_cooldown_bot.open_raid import OpenRaid, build_raid_embed
from off_cooldown_bot.settings import settings from off_cooldown_bot.settings import settings
@@ -26,35 +25,14 @@ class DailyLoop(commands.Cog, name="Daily Loop"):
self.update_birthdays() self.update_birthdays()
self.daily_loop.start() self.daily_loop.start()
@tasks.loop(time=time(hour=0, tzinfo=UTC)) @tasks.loop(time=time(hour=0, tzinfo=timezone("UTC")))
async def daily_loop(self) -> None: async def daily_loop(self) -> None:
"""Run daily repeated functions.""" """Run daily repeated functions."""
self.update_birthdays() self.update_birthdays()
await self.cakedays() await self.cakedays()
@tasks.loop(time=time(hour=20, tzinfo=timezone("CST")))
async def open_raid(self) -> None:
"""
Define the open raid loop.
Checks daily if it is Thursday and then posts the open raid sign up.
"""
today = datetime.now(timezone("CST"))
if today.day + 2 == 5:
# open raid is on Saturday, post 2 days before
if (guild := self.bot.get_guild(settings.params.guild_id)) is None:
ocd_logger.error("Guild id not correct.")
return
if (channel := guild.get_channel(settings.channel_ids.raid)) is None or not isinstance(
channel, nextcord.TextChannel
):
ocd_logger.error("Raid channel is not defined or is not a text channel.")
return
await channel.send(embed=build_raid_embed(), view=OpenRaid())
@daily_loop.before_loop @daily_loop.before_loop
@open_raid.before_loop
async def before_loop(self) -> None: async def before_loop(self) -> None:
"""Actions run before the loop starts. Want to wait for bot to be ready and get the current cycle.""" """Actions run before the loop starts. Want to wait for bot to be ready and get the current cycle."""
await self.bot.wait_until_ready() await self.bot.wait_until_ready()
-151
View File
@@ -1,151 +0,0 @@
"""Contains functions for open raid sign-ups."""
import datetime
import nextcord
from off_cooldown_bot.logger import ocd_logger
MAX_TANKS = 2
MAX_HEALERS = 2
MAX_DPS = 25
class OpenRaid(nextcord.ui.View):
"""Class defines view for buttons on an open raid schedule message."""
def __init__(self) -> None:
super().__init__(timeout=None, auto_defer=True)
@nextcord.ui.button(label="Tank", style=nextcord.ButtonStyle.blurple, emoji="🛡️", custom_id="open_raid_tank")
async def tank(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
"""
Signs a user up as a tank.
Removes them if they are already signed up.
Args:
button (nextcord.ui.Button): Un-used.
interaction (nextcord.Interaction): Interaction with command.
"""
if interaction.message is None or interaction.user is None:
ocd_logger.warning("Command was called without a message or user.")
return
embed = interaction.message.embeds[0]
user_str = f"<@{interaction.user.id}>"
for index, field in enumerate(embed.fields):
if field.name == "Tanks":
values = [] if field.value is None else field.value.split("\n")
if user_str in values:
values.remove(user_str)
else:
if len(values) >= MAX_TANKS:
await interaction.response.send_message(
"Enough tanks have signed up, please choose another role.", ephemeral=True
)
return
values.append(user_str)
embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False)
break
await interaction.edit(embed=embed)
@nextcord.ui.button(label="Healer", style=nextcord.ButtonStyle.green, emoji="❤️", custom_id="open_raid_healer")
async def healer(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
"""
Signs a user up as a healer.
Removes them if they are already signed up.
Args:
button (nextcord.ui.Button): Un-used.
interaction (nextcord.Interaction): Interaction with command.
"""
if interaction.message is None or interaction.user is None:
ocd_logger.warning("Command was called without a message or user.")
return
embed = interaction.message.embeds[0]
user_str = f"<@{interaction.user.id}>"
for index, field in enumerate(embed.fields):
if field.name == "Healers":
values = [] if field.value is None else field.value.split("\n")
if user_str in values:
values.remove(user_str)
else:
if len(values) >= MAX_HEALERS:
await interaction.response.send_message(
"Enough healers have signed up, please choose another role.", ephemeral=True
)
return
values.append(user_str)
embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False)
break
await interaction.edit(embed=embed)
@nextcord.ui.button(label="DPS", style=nextcord.ButtonStyle.red, emoji="⚔️", custom_id="open_raid_dps")
async def dps(self, button: nextcord.ui.Button, interaction: nextcord.Interaction) -> None: # noqa: ARG002
"""
Signs a user up as dps.
Removes them if they are already signed up.
Args:
button (nextcord.ui.Button): Un-used.
interaction (nextcord.Interaction): Interaction with command.
"""
if interaction.message is None or interaction.user is None:
ocd_logger.warning("Command was called without a message or user.")
return
embed = interaction.message.embeds[0]
user_str = f"<@{interaction.user.id}>"
for index, field in enumerate(embed.fields):
if field.name == "DPS":
values = [] if field.value is None else field.value.split("\n")
if user_str in values:
values.remove(user_str)
else:
if len(values) >= MAX_DPS:
await interaction.response.send_message(
"Enough dps have signed up, please choose another role.", ephemeral=True
)
return
values.append(user_str)
embed.set_field_at(index, name=field.name, value="\n".join(values), inline=False)
break
await interaction.edit(embed=embed)
def build_raid_embed() -> nextcord.Embed:
"""
Build the open raid embed.
Returns:
nextcord.Embed: Embed that shows the raid's sign-ups.
"""
today = datetime.datetime.now(tz=datetime.UTC).replace(hour=20)
saturday_idx = 5
days_delta = saturday_idx - today.weekday()
if days_delta < 0:
days_delta += 7
raid_time = today + datetime.timedelta(days_delta)
embed = nextcord.Embed(
title="Off Cooldown Open Raid", description=f"Raid time: t:{int(raid_time.timestamp())}:F", timestamp=raid_time
)
embed.add_field(name="Tanks", value="", inline=False)
embed.add_field(name="Healers", value="", inline=False)
embed.add_field(name="DPS", value="", inline=False)
return embed
-1
View File
@@ -12,7 +12,6 @@ class ChannelIds:
"""Class holds all channel ids needed by bot.""" """Class holds all channel ids needed by bot."""
general: int general: int
raid: int
@dataclass @dataclass
-3
View File
@@ -1,3 +0,0 @@
"""File contains functions and variables used widely."""
GUILDS = [1000247361639030804, 822199658306076672]