Compare commits

...
7 Commits
Author SHA1 Message Date
imcompiling a277566654 Merge commit '58c167bbe30fa422277bef9e1ad0aed7bc350fc4' into missed-election 2025-04-23 14:54:01 -04:00
imcompiling 6adb98111b Add the freezegun module for testing. 2025-04-23 14:22:29 -04:00
imcompiling 4d96aebeb1 Address some pylance warnings. 2025-04-23 14:15:39 -04:00
imcompiling d38f56ff41 Rename module to conform to naming conventions. 2025-04-23 14:07:46 -04:00
imcompiling 95fb9e289b Imports got sorted, address some pylance warnings. 2025-04-23 14:05:36 -04:00
imcompiling 3bcd1a3a01 Update settings to handle lists
build_develop / build (push) Successful in 34s
lists won't ever happen, but pylance didn't like it.
2025-04-23 14:03:50 -04:00
imcompiling 6c57644eb0 Add pytest and coverage.
build_develop / build (push) Successful in 1m11s
2025-04-23 13:22:41 -04:00
15 changed files with 54 additions and 47 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ from dakiny_bot.classes.voting_highcouncil_views import VoteHighcouncilView
from dakiny_bot.classes.voting_views import VoteView from dakiny_bot.classes.voting_views import VoteView
from dakiny_bot.database import create_database from dakiny_bot.database import create_database
from .DakinySettings import settings from .dakiny_settings import settings
birthday_list: list[int] = [] birthday_list: list[int] = []
+7 -8
View File
@@ -5,14 +5,11 @@ from datetime import UTC, datetime, timedelta
from pathlib import Path from pathlib import Path
import nextcord import nextcord
from sqlalchemy import select, true, update
from sqlalchemy.orm import Session
from dakiny_bot.classes.nominate_highcouncil_views import NominateHighCouncilView from dakiny_bot.classes.nominate_highcouncil_views import NominateHighCouncilView
from dakiny_bot.classes.nominate_views import NominateView from dakiny_bot.classes.nominate_views import NominateView
from dakiny_bot.classes.voting_highcouncil_views import VoteHighcouncilView from dakiny_bot.classes.voting_highcouncil_views import VoteHighcouncilView
from dakiny_bot.classes.voting_views import VoteView from dakiny_bot.classes.voting_views import VoteView
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.sql_data_classes import ( from dakiny_bot.database.sql_data_classes import (
CouncilMembers, CouncilMembers,
ElectionInformation, ElectionInformation,
@@ -28,6 +25,8 @@ from dakiny_bot.utils import (
get_datetime, get_datetime,
get_election_name, get_election_name,
) )
from sqlalchemy import select, true, update
from sqlalchemy.orm import Session
REQUIRED_VOTES_TO_BE_ELECTED = 3 REQUIRED_VOTES_TO_BE_ELECTED = 3
@@ -70,7 +69,7 @@ class Election:
list[str]: A list of message contents in the correct order. Must be a string because the message is too list[str]: A list of message contents in the correct order. Must be a string because the message is too
long. long.
""" """
with Path(f"{TEMPLATES_DIR}/election_announcement.txt", encoding="utf8").open() as file: with Path(f"{TEMPLATES_DIR}/election_announcement.txt").open() as file:
message = file.read() message = file.read()
next_election = get_datetime( next_election = get_datetime(
@@ -98,7 +97,7 @@ class Election:
Returns: Returns:
str: Message to send. str: Message to send.
""" """
with Path(f"{TEMPLATES_DIR}/highcouncil_election.txt", encoding="utf8").open() as file: with Path(f"{TEMPLATES_DIR}/highcouncil_election.txt").open() as file:
message = file.read() message = file.read()
return message.format( return message.format(
@@ -116,7 +115,7 @@ class Election:
Returns: Returns:
str: Message to send. str: Message to send.
""" """
with Path(f"{TEMPLATES_DIR}/highcouncil_vote.txt", encoding="utf8").open() as file: with Path(f"{TEMPLATES_DIR}/highcouncil_vote.txt").open() as file:
message = file.read() message = file.read()
return message.format( return message.format(
@@ -131,7 +130,7 @@ class Election:
Returns: Returns:
str: Message to send str: Message to send
""" """
with Path(f"{TEMPLATES_DIR}/vote_start.txt", encoding="utf8").open() as file: with Path(f"{TEMPLATES_DIR}/vote_start.txt").open() as file:
message = file.read() message = file.read()
vote_end: datetime = get_datetime(settings.election_cycles[self.cycle].voting_end) vote_end: datetime = get_datetime(settings.election_cycles[self.cycle].voting_end)
@@ -1,11 +1,7 @@
"""Contains various views to be used in the high council nomination process.""" """Contains various views to be used in the high council nomination process."""
import nextcord import nextcord
from nextcord.interactions import Interaction from dakiny_bot.dakiny_settings import settings
from sqlalchemy import select
from sqlalchemy.orm import Session
from dakiny_bot.DakinySettings import settings
from dakiny_bot.database.sql_data_classes import CouncilMembers, engine from dakiny_bot.database.sql_data_classes import CouncilMembers, engine
from dakiny_bot.utils import ( from dakiny_bot.utils import (
NOMINEE_SPLITTER, NOMINEE_SPLITTER,
@@ -13,6 +9,9 @@ from dakiny_bot.utils import (
decorate_dm_nomination, decorate_dm_nomination,
get_election_name, get_election_name,
) )
from nextcord.interactions import Interaction
from sqlalchemy import select
from sqlalchemy.orm import Session
class NominateDMModal(nextcord.ui.Modal): class NominateDMModal(nextcord.ui.Modal):
+3 -4
View File
@@ -1,14 +1,13 @@
"""Contains various views to be used in the nomination process.""" """Contains various views to be used in the nomination process."""
import nextcord import nextcord
from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.sql_data_classes import CouncilMembers, engine
from dakiny_bot.utils import NOMINEE_SPLITTER, decorate_nomination, get_election_name
from nextcord.interactions import Interaction from nextcord.interactions import Interaction
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from dakiny_bot.DakinySettings import settings
from dakiny_bot.database.sql_data_classes import CouncilMembers, engine
from dakiny_bot.utils import NOMINEE_SPLITTER, decorate_nomination, get_election_name
class NominateModal(nextcord.ui.Modal): class NominateModal(nextcord.ui.Modal):
""" """
@@ -1,12 +1,7 @@
"""Contains various views to be used while voting for high council. Controls the logic when performing the vote.""" """Contains various views to be used while voting for high council. Controls the logic when performing the vote."""
import nextcord import nextcord
from nextcord import SelectOption from dakiny_bot.dakiny_settings import settings
from nextcord.interactions import Interaction
from sqlalchemy import exc, select, update
from sqlalchemy.orm import Session
from dakiny_bot.DakinySettings import settings
from dakiny_bot.database.sql_data_classes import ( from dakiny_bot.database.sql_data_classes import (
CouncilMembers, CouncilMembers,
ElectionInformation, ElectionInformation,
@@ -14,6 +9,10 @@ from dakiny_bot.database.sql_data_classes import (
engine, engine,
) )
from dakiny_bot.utils import VoteType, build_highcouncil_votes_str, get_election_name from dakiny_bot.utils import VoteType, build_highcouncil_votes_str, get_election_name
from nextcord import SelectOption
from nextcord.interactions import Interaction
from sqlalchemy import exc, select, update
from sqlalchemy.orm import Session
class VoteSelect(nextcord.ui.StringSelect): class VoteSelect(nextcord.ui.StringSelect):
+5 -6
View File
@@ -1,12 +1,7 @@
"""Contains various views to be used while voting. Controls the logic when performing the vote.""" """Contains various views to be used while voting. Controls the logic when performing the vote."""
import nextcord import nextcord
from nextcord import SelectOption from dakiny_bot.dakiny_settings import settings
from nextcord.interactions import Interaction
from sqlalchemy import exc, select, update
from sqlalchemy.orm import Session
from dakiny_bot.DakinySettings import settings
from dakiny_bot.database.sql_data_classes import ( from dakiny_bot.database.sql_data_classes import (
CouncilMembers, CouncilMembers,
ElectionInformation, ElectionInformation,
@@ -14,6 +9,10 @@ from dakiny_bot.database.sql_data_classes import (
engine, engine,
) )
from dakiny_bot.utils import VoteType, build_votes_str, get_election_name from dakiny_bot.utils import VoteType, build_votes_str, get_election_name
from nextcord import SelectOption
from nextcord.interactions import Interaction
from sqlalchemy import exc, select, update
from sqlalchemy.orm import Session
class VoteSelect(nextcord.ui.StringSelect): class VoteSelect(nextcord.ui.StringSelect):
+1 -1
View File
@@ -9,7 +9,7 @@ from git import Repo
from nextcord.ext import commands from nextcord.ext import commands
from dakiny_bot.classes.gitea_webhook import GiteaWebhook from dakiny_bot.classes.gitea_webhook import GiteaWebhook
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.utils import REPO_DIR, edit_clan_council_info, update_clan_messages from dakiny_bot.utils import REPO_DIR, edit_clan_council_info, update_clan_messages
if TYPE_CHECKING: if TYPE_CHECKING:
+1 -1
View File
@@ -4,7 +4,7 @@ import nextcord
from discord import TextInputStyle from discord import TextInputStyle
from nextcord.ext import commands from nextcord.ext import commands
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.utils import GUILDS, MAX_DISCORD_MESSAGE_LENGTH, PointType, record_points from dakiny_bot.utils import GUILDS, MAX_DISCORD_MESSAGE_LENGTH, PointType, record_points
+1 -1
View File
@@ -4,7 +4,7 @@ import nextcord
from nextcord.ext import commands from nextcord.ext import commands
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.sql_data_classes import Presences, engine from dakiny_bot.database.sql_data_classes import Presences, engine
+1 -1
View File
@@ -3,7 +3,7 @@
import nextcord import nextcord
from nextcord.ext import commands from nextcord.ext import commands
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.utils import GUILDS from dakiny_bot.utils import GUILDS
+1 -1
View File
@@ -4,7 +4,7 @@ import nextcord
from nextcord.ext import application_checks, commands from nextcord.ext import application_checks, commands
from dakiny_bot.classes.election import Election from dakiny_bot.classes.election import Election
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.utils import GUILDS, get_active_election_cycle, get_quarter_name from dakiny_bot.utils import GUILDS, get_active_election_cycle, get_quarter_name
ME = 206602713511886849 ME = 206602713511886849
+1 -1
View File
@@ -11,7 +11,7 @@ from sqlalchemy.orm import Session
from dakiny_bot.app import birthday_list from dakiny_bot.app import birthday_list
from dakiny_bot.classes.election import Election from dakiny_bot.classes.election import Election
from dakiny_bot.DakinySettings import settings from dakiny_bot.dakiny_settings import settings
from dakiny_bot.database.sql_data_classes import UserBirthday, engine from dakiny_bot.database.sql_data_classes import UserBirthday, engine
from dakiny_bot.utils import get_active_election_cycle from dakiny_bot.utils import get_active_election_cycle
@@ -83,4 +83,5 @@ class DakinySettings(YAMLWizard):
self.to_yaml_file(CONFIG_LOCATION) self.to_yaml_file(CONFIG_LOCATION)
settings = DakinySettings.from_yaml_file(CONFIG_LOCATION) tmp = DakinySettings.from_yaml_file(CONFIG_LOCATION)
settings: DakinySettings = tmp[0] if isinstance(tmp, list) else tmp
+15 -9
View File
@@ -21,7 +21,7 @@ from dakiny_bot.database.sql_data_classes import (
engine, engine,
) )
from .DakinySettings import settings from .dakiny_settings import settings
NOMINEE_SPLITTER = "========================================\n\n" NOMINEE_SPLITTER = "========================================\n\n"
REPO_DIR = "./dakiny-messages" REPO_DIR = "./dakiny-messages"
@@ -34,20 +34,20 @@ VoteType = StrEnum("VoteType", ["COUNCIL", "DISCORDMANAGER", "CLANLEADER"])
PointType = StrEnum("PointType", ["CLAN", "EVENT"]) PointType = StrEnum("PointType", ["CLAN", "EVENT"])
def get_datetime(day: str) -> datetime: def get_datetime(month_day: str) -> datetime:
""" """
Takes in a string month and day and returns a datetime object of that Month/Day this year. Takes in a string month and day and returns a datetime object of that Month/Day this year.
Args: Args:
day (str): Month/Day in that format. month_day (str): Month/Day in that format.
Returns: Returns:
datetime: Datetime representation of Month/Day. datetime: Datetime representation of Month/Day.
""" """
today = datetime.now(tz=UTC).date() today = datetime.now(tz=UTC).date()
year = today.year year = today.year
month = int(day.split("/")[0]) month = int(month_day.split("/")[0])
day = int(day.split("/")[1]) day = int(month_day.split("/")[1])
# ensure that year rolls over if current month is December and the next month is less than 12. # ensure that year rolls over if current month is December and the next month is less than 12.
if today.month == calendar.DECEMBER and month < calendar.OCTOBER: if today.month == calendar.DECEMBER and month < calendar.OCTOBER:
@@ -66,7 +66,10 @@ def get_election_name() -> str:
Returns: Returns:
str: the name of the election cycle str: the name of the election cycle
""" """
cycle = get_active_election_cycle() if cycle := get_active_election_cycle() is None:
# undefined behavior
print("Did not find an active election cycle. Undefined behavior with return string.") # noqa: T201
return "No-active-election-cycle"
current_cycle = settings.election_cycles[cycle] current_cycle = settings.election_cycles[cycle]
return f"vote-{get_datetime(current_cycle.term_start).year}-{current_cycle.name}" return f"vote-{get_datetime(current_cycle.term_start).year}-{current_cycle.name}"
@@ -78,13 +81,16 @@ def get_quarter_name() -> str:
Returns: Returns:
str: the name of the cycle. str: the name of the cycle.
""" """
cycle = get_quarter_cycle() if cycle := get_quarter_cycle() is None:
# undefined behavior
print("Did not find a quarter cycle. Undefined behavior with return string.") # noqa: T201
return "no-quarter-cycle"
current_cycle = settings.election_cycles[cycle] current_cycle = settings.election_cycles[cycle]
return f"{get_datetime(current_cycle.term_start).year}-{current_cycle.name}" return f"{get_datetime(current_cycle.term_start).year}-{current_cycle.name}"
def get_active_election_cycle() -> int: def get_active_election_cycle() -> int | None:
""" """
Returns index for active election. An election is considered active between the election start and the term start. Returns index for active election. An election is considered active between the election start and the term start.
@@ -104,7 +110,7 @@ def get_active_election_cycle() -> int:
return get_quarter_cycle() return get_quarter_cycle()
def get_quarter_cycle() -> int: def get_quarter_cycle() -> int | None:
""" """
Returns the index for the current cycle/quarter. Defined as between term start and end. Returns the index for the current cycle/quarter. Defined as between term start and end.
+6 -1
View File
@@ -19,7 +19,12 @@ description = "Dakiny's Discord Bot."
readme = "README.md" readme = "README.md"
[dependency-groups] [dependency-groups]
dev = ["ruff<1.0.0,>=0.6.9"] dev = [
"freezegun>=1.5.1",
"pytest>=8.3.5",
"pytest-cov>=6.1.1",
"ruff<1.0.0,>=0.6.9",
]
[tool.ruff] [tool.ruff]
# Exclude a variety of commonly ignored directories. # Exclude a variety of commonly ignored directories.