Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e686cf88e5 | ||
|
|
117dea48c4 | ||
|
|
62e4417ce8 | ||
|
|
672df41f19 | ||
|
|
328f3fea78 | ||
|
|
18751bc85c | ||
|
|
e243b40be7 | ||
|
|
7a91cd37ec | ||
|
|
efadcb30c7 | ||
|
|
1a8c5616ef | ||
|
|
0710db0654 | ||
|
|
077119acdd | ||
|
|
ac8d1bc681 | ||
|
|
df8cb3dd49 |
@@ -34,16 +34,16 @@ The Clan Council will be denoted by the Discord ranks of <@&{clan_council_id}> a
|
|||||||
<:Rank_Owner:479008325137072155> Clan Leader
|
<:Rank_Owner:479008325137072155> Clan Leader
|
||||||
---message_break---
|
---message_break---
|
||||||
__Here's the timeline:__
|
__Here's the timeline:__
|
||||||
Election begins: {election_start_date}
|
Election begins: {election_start}
|
||||||
Term: {term_start_date} - {term_end_date}
|
Term: {term_start} - {term_end}
|
||||||
|
|
||||||
**{election_start_date}**: Post here to announce candidacy
|
**{election_start}**: Post here to announce candidacy
|
||||||
**{voting_start_date}**: Voting begins
|
**{voting_start}**: Voting begins
|
||||||
**{voting_end_date}**: Votes are tallied and winners are announced
|
**{voting_end}**: Votes are tallied and winners are announced
|
||||||
**{highcouncil_election_date}**: The new Clan Council votes who among them shall receive the two High Council positions of: Clan Leader and Discord Server Manager.
|
**{highcouncil_election}**: The new Clan Council votes who among them shall receive the two High Council positions of: Clan Leader and Discord Server Manager.
|
||||||
**{term_start_date}**: The new Clan Council is officially inaugurated and a drop party (or a giveaway event) begins to commemorate the new leadership.
|
**{term_start}**: The new Clan Council is officially inaugurated and a drop party (or a giveaway event) begins to commemorate the new leadership.
|
||||||
|
|
||||||
This process will begin again next quarter on {next_election_start_date} with the inauguration scheduled for {term_end_date}.
|
This process will begin again next quarter on {next_election_start} with the inauguration scheduled for {term_end}.
|
||||||
---message_break---
|
---message_break---
|
||||||
**You may now announce your candidacy for a seat on the Dakiny Clan Council!
|
**You may now announce your candidacy for a seat on the Dakiny Clan Council!
|
||||||
**
|
**
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<@&{clan_member_id}>, it's time to vote for clan council.
|
<@&{clan_member_id}>, it's time to vote for clan council.
|
||||||
|
|
||||||
React with <{voting_emote_id}> to vote.
|
React with <{voting_emote_id}> to vote.
|
||||||
Voting ends next {voting_end_day}, {voting_end_date}.
|
Voting ends next {voting_end_day}, {voting_end}.
|
||||||
Results will then be announced.
|
Results will then be announced.
|
||||||
|
|
||||||
After a candidate receives 3 votes, their spot is secured in the new council, but you can still vote for them to show your support.
|
After a candidate receives 3 votes, their spot is secured in the new council, but you can still vote for them to show your support.
|
||||||
|
|||||||
+16
-15
@@ -2,7 +2,7 @@
|
|||||||
Contains the election cycle class
|
Contains the election cycle class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
|
|
||||||
import nextcord
|
import nextcord
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
@@ -20,6 +20,7 @@ class ElectionCycle:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cycle: int, config: DakinyConfig, guild: nextcord.Guild) -> None:
|
def __init__(self, cycle: int, config: DakinyConfig, guild: nextcord.Guild) -> None:
|
||||||
|
# TODO update
|
||||||
"""
|
"""
|
||||||
Generates all dates relevant to the election cycle from input election start, term start and end dates.
|
Generates all dates relevant to the election cycle from input election start, term start and end dates.
|
||||||
|
|
||||||
@@ -37,9 +38,9 @@ class ElectionCycle:
|
|||||||
self.term_end: datetime = get_datetime(self.elecion_cycle.term_end)
|
self.term_end: datetime = get_datetime(self.elecion_cycle.term_end)
|
||||||
self.voting_start: datetime = get_datetime(self.elecion_cycle.voting_start)
|
self.voting_start: datetime = get_datetime(self.elecion_cycle.voting_start)
|
||||||
self.voting_end: datetime = get_datetime(self.elecion_cycle.voting_end)
|
self.voting_end: datetime = get_datetime(self.elecion_cycle.voting_end)
|
||||||
self.highcouncil_election_announce: datetime = self.voting_end + timedelta(days=1)
|
self.highcouncil_election_announce: datetime = get_datetime(self.elecion_cycle.highcouncil_election_announce)
|
||||||
self.highcouncil_election_start: datetime = self.highcouncil_election_announce + timedelta(days=3)
|
self.highcouncil_election_start: datetime = get_datetime(self.elecion_cycle.highcouncil_election_start)
|
||||||
self.highcouncil_election_end: datetime = self.term_start - timedelta(days=1)
|
self.highcouncil_election_end: datetime = get_datetime(self.elecion_cycle.highcouncil_election_end)
|
||||||
self.guild: nextcord.Guild = guild
|
self.guild: nextcord.Guild = guild
|
||||||
self.election_over: bool = False
|
self.election_over: bool = False
|
||||||
|
|
||||||
@@ -60,13 +61,13 @@ class ElectionCycle:
|
|||||||
message = message.format(
|
message = message.format(
|
||||||
clan_council_id=self.config.params.clan_council_role_id,
|
clan_council_id=self.config.params.clan_council_role_id,
|
||||||
high_council_id=self.config.params.high_council_role_id,
|
high_council_id=self.config.params.high_council_role_id,
|
||||||
election_start_date=self.election_start.strftime("%B %d"),
|
election_start=self.election_start.strftime("%B %d"),
|
||||||
term_start_date=self.term_start.strftime("%B %d"),
|
term_start=self.term_start.strftime("%B %d"),
|
||||||
term_end_date=self.term_end.strftime("%B %d"),
|
term_end=self.term_end.strftime("%B %d"),
|
||||||
voting_start_date=self.voting_start.strftime("%B %d"),
|
voting_start=self.voting_start.strftime("%B %d"),
|
||||||
voting_end_date=self.voting_end.strftime("%B %d"),
|
voting_end=self.voting_end.strftime("%B %d"),
|
||||||
highcouncil_election_date=self.highcouncil_election_start.strftime("%B %d"),
|
highcouncil_election=self.highcouncil_election_start.strftime("%B %d"),
|
||||||
next_election_start_date=next_election.strftime("%B %d"),
|
next_election_start=next_election.strftime("%B %d"),
|
||||||
)
|
)
|
||||||
|
|
||||||
return message.split("---message_break---")
|
return message.split("---message_break---")
|
||||||
@@ -87,7 +88,7 @@ class ElectionCycle:
|
|||||||
highcouncil_election_announce=self.highcouncil_election_announce.strftime("%B %d"),
|
highcouncil_election_announce=self.highcouncil_election_announce.strftime("%B %d"),
|
||||||
highcouncil_election_start=self.highcouncil_election_start.strftime("%B %d"),
|
highcouncil_election_start=self.highcouncil_election_start.strftime("%B %d"),
|
||||||
highcouncil_election_end=self.highcouncil_election_end.strftime("%B %d"),
|
highcouncil_election_end=self.highcouncil_election_end.strftime("%B %d"),
|
||||||
term_start_date=self.term_start.strftime("%B %d"),
|
term_start=self.term_start.strftime("%B %d"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def build_highcouncil_vote_start(self) -> str:
|
def build_highcouncil_vote_start(self) -> str:
|
||||||
@@ -103,7 +104,7 @@ class ElectionCycle:
|
|||||||
|
|
||||||
return message.format(
|
return message.format(
|
||||||
clan_council_elect_role_id=self.config.params.clan_council_elect_role_id,
|
clan_council_elect_role_id=self.config.params.clan_council_elect_role_id,
|
||||||
term_start_date=self.term_start.strftime("%B %d"),
|
term_start=self.term_start.strftime("%B %d"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def build_vote_start(self) -> str:
|
def build_vote_start(self) -> str:
|
||||||
@@ -121,7 +122,7 @@ class ElectionCycle:
|
|||||||
return message.format(
|
return message.format(
|
||||||
clan_member_id=self.config.params.clan_member_role_id,
|
clan_member_id=self.config.params.clan_member_role_id,
|
||||||
voting_emote_id=self.config.params.voting_emote_id,
|
voting_emote_id=self.config.params.voting_emote_id,
|
||||||
voting_end_date=vote_end.strftime("%B %d"),
|
voting_end=vote_end.strftime("%B %d"),
|
||||||
voting_end_day=vote_end.strftime("%A"),
|
voting_end_day=vote_end.strftime("%A"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ class ElectionCycle:
|
|||||||
if today.date() == self.election_start.date():
|
if today.date() == self.election_start.date():
|
||||||
await self.election_start_action()
|
await self.election_start_action()
|
||||||
elif today.date() == self.voting_start.date():
|
elif today.date() == self.voting_start.date():
|
||||||
await self.voting_end_action()
|
await self.voting_start_action()
|
||||||
elif today.date() == self.voting_end.date():
|
elif today.date() == self.voting_end.date():
|
||||||
await self.voting_end_action()
|
await self.voting_end_action()
|
||||||
elif today.date() == self.highcouncil_election_start.date():
|
elif today.date() == self.highcouncil_election_start.date():
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Cog loader. Adds all command cogs to the bot.
|
|||||||
from nextcord.ext import commands
|
from nextcord.ext import commands
|
||||||
|
|
||||||
from cogs.commands.request import RequestCog
|
from cogs.commands.request import RequestCog
|
||||||
|
from cogs.commands.set import setCog
|
||||||
from cogs.commands.test import TestCog
|
from cogs.commands.test import TestCog
|
||||||
|
|
||||||
|
|
||||||
@@ -14,5 +15,7 @@ def setup(bot: commands.Bot):
|
|||||||
"""
|
"""
|
||||||
Adds all command classes to bot.
|
Adds all command classes to bot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bot.add_cog(RequestCog(bot))
|
bot.add_cog(RequestCog(bot))
|
||||||
bot.add_cog(TestCog(bot))
|
bot.add_cog(TestCog(bot))
|
||||||
|
bot.add_cog(setCog())
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
"""
|
||||||
|
Contains commands and views for set commands.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import nextcord
|
||||||
|
from nextcord.ext import commands
|
||||||
|
from sqlalchemy import delete, select
|
||||||
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from dakiny_bot import birthday_list
|
||||||
|
from database_setup.sql_data_classes import UserBirthday, engine
|
||||||
|
|
||||||
|
|
||||||
|
class setCog(commands.Cog, name="Set Commands"):
|
||||||
|
"""
|
||||||
|
Class holds set commands.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
"""
|
||||||
|
Default constructor for SetCog class. Does nothing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@nextcord.slash_command()
|
||||||
|
async def set(self, interaction: nextcord.Interaction):
|
||||||
|
"""
|
||||||
|
Parent slash command for set. Never called.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@set.subcommand(description="Sets your birth month and day for the Birthday Fun. Use 0/0 to remove yourself.")
|
||||||
|
async def birthday(
|
||||||
|
self,
|
||||||
|
interaction: nextcord.Interaction,
|
||||||
|
month: int = nextcord.SlashOption(required=True, min_value=0, max_value=12, description="Your birth month."),
|
||||||
|
day: int = nextcord.SlashOption(required=True, min_value=0, max_value=31, description="Your birth day."),
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Sets a user's birthday in the database. Removes on input 0/0. If birthday is today, adds to the birthday_list.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (nextcord.Interaction): Interaction that invoked the command.
|
||||||
|
month (int, optional): The month a user was born. Is SlashOption.
|
||||||
|
day (int, optional): The day a user was born. Is SlashOption.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Must be deferred, apparently datetime takes a little bit on invalid dates.
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
if month == 0 and day == 0:
|
||||||
|
stmt = delete(UserBirthday).where(UserBirthday.UserId == interaction.user.id)
|
||||||
|
with Session(engine) as session:
|
||||||
|
session.execute(stmt)
|
||||||
|
session.commit()
|
||||||
|
await interaction.followup.send("Removed birthday.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# check if valid day
|
||||||
|
today = datetime.today()
|
||||||
|
try:
|
||||||
|
birthday = datetime(today.year, month, day)
|
||||||
|
except ValueError:
|
||||||
|
await interaction.followup.send(f"Invalid date: {month}/{day}.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# If the birthday is today, add to birthday_list
|
||||||
|
if today.date() == birthday.date():
|
||||||
|
birthday_list.append(interaction.user.id)
|
||||||
|
|
||||||
|
new_birthday = UserBirthday(UserId=interaction.user.id, Birthday=f"{month}/{day}")
|
||||||
|
with Session(engine) as session:
|
||||||
|
try:
|
||||||
|
session.add(new_birthday)
|
||||||
|
session.commit()
|
||||||
|
except IntegrityError:
|
||||||
|
# User already has birthday, change it instead.
|
||||||
|
session.rollback()
|
||||||
|
stmt = select(UserBirthday).where(UserBirthday.UserId == interaction.user.id)
|
||||||
|
new_birthday = session.scalar(stmt)
|
||||||
|
new_birthday.Birthday = f"{month}/{day}"
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
await interaction.followup.send(f"Birthday set to {month}/{day}.", ephemeral=True)
|
||||||
@@ -2,13 +2,19 @@
|
|||||||
Defines the daily loop that runs the Dakiny bot functions.
|
Defines the daily loop that runs the Dakiny bot functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
|
|
||||||
|
import nextcord
|
||||||
from nextcord.ext import commands, tasks
|
from nextcord.ext import commands, tasks
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
from sqlalchemy import select
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from classes.election_cycle import ElectionCycle
|
from classes.election_cycle import ElectionCycle
|
||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
|
from dakiny_bot import birthday_list
|
||||||
|
from database_setup.sql_data_classes import UserBirthday, engine
|
||||||
from utils import get_datetime
|
from utils import get_datetime
|
||||||
|
|
||||||
|
|
||||||
@@ -20,6 +26,7 @@ class DailyLoop(commands.Cog, name="Daily Loop"):
|
|||||||
def __init__(self, bot: commands.Bot) -> None:
|
def __init__(self, bot: commands.Bot) -> None:
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.current_election = None
|
self.current_election = None
|
||||||
|
self.update_birthdays()
|
||||||
|
|
||||||
# pylint doesn't recognize that daily_loop is subclassed from tasks.loop.
|
# pylint doesn't recognize that daily_loop is subclassed from tasks.loop.
|
||||||
self.daily_loop.start() # pylint: disable=no-member
|
self.daily_loop.start() # pylint: disable=no-member
|
||||||
@@ -40,6 +47,13 @@ class DailyLoop(commands.Cog, name="Daily Loop"):
|
|||||||
if self.current_election.election_over:
|
if self.current_election.election_over:
|
||||||
self.current_election = None
|
self.current_election = None
|
||||||
|
|
||||||
|
self.update_birthdays()
|
||||||
|
|
||||||
|
if 239547993106284544 in birthday_list:
|
||||||
|
# inform kandy that it is her "birthday"
|
||||||
|
kandy: nextcord.User = await self.bot.fetch_user(239547993106284544)
|
||||||
|
await kandy.send('Happy "Birthday"!')
|
||||||
|
|
||||||
@daily_loop.before_loop
|
@daily_loop.before_loop
|
||||||
async def before_loop(self):
|
async def before_loop(self):
|
||||||
"""
|
"""
|
||||||
@@ -67,8 +81,26 @@ class DailyLoop(commands.Cog, name="Daily Loop"):
|
|||||||
for cycle, election in enumerate(config.election_cycles):
|
for cycle, election in enumerate(config.election_cycles):
|
||||||
if (
|
if (
|
||||||
today.date() >= get_datetime(election.election_start).date()
|
today.date() >= get_datetime(election.election_start).date()
|
||||||
and today.date() < get_datetime(election.term_start).date()
|
and today.date() <= get_datetime(election.term_start).date()
|
||||||
):
|
):
|
||||||
current_election = ElectionCycle(cycle, config, self.bot.get_guild(config.params.guild_id))
|
current_election = ElectionCycle(cycle, config, self.bot.get_guild(config.params.guild_id))
|
||||||
|
|
||||||
return current_election
|
return current_election
|
||||||
|
|
||||||
|
def update_birthdays(self) -> None:
|
||||||
|
"""
|
||||||
|
Goes through database to collect all birthdays that are today. Adds user's id to birthday list.
|
||||||
|
"""
|
||||||
|
birthday_list.clear()
|
||||||
|
|
||||||
|
# kandy's 1% chance
|
||||||
|
if random.randint(0, 99) == 0:
|
||||||
|
birthday_list.append(239547993106284544)
|
||||||
|
|
||||||
|
today = datetime.today()
|
||||||
|
birthday = f"{today.month}/{today.day}"
|
||||||
|
|
||||||
|
stmt = select(UserBirthday.UserId).where(UserBirthday.Birthday == birthday)
|
||||||
|
with Session(engine) as session:
|
||||||
|
to_add = session.scalars(stmt)
|
||||||
|
birthday_list.extend(to_add.all())
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
"""
|
||||||
|
Defines cog for on message listener.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import nextcord
|
||||||
|
from nextcord.ext import commands
|
||||||
|
|
||||||
|
from dakiny_bot import birthday_list
|
||||||
|
|
||||||
|
|
||||||
|
class SubmissionListener(commands.Cog, name="Message Listener"):
|
||||||
|
"""Sets up message listener."""
|
||||||
|
|
||||||
|
def __init__(self, bot: commands.Bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_message(self, message: nextcord.Message):
|
||||||
|
"""Listener for message creation. Adds score and attachments to submission."""
|
||||||
|
# don't want to process any messages from bot.
|
||||||
|
if message.author.id == self.bot.user.id:
|
||||||
|
return
|
||||||
|
|
||||||
|
await birthday_action(message)
|
||||||
|
|
||||||
|
|
||||||
|
# This function will be called when this extension is loaded.
|
||||||
|
# It is necessary to add these functions to the bot.
|
||||||
|
def setup(bot: commands.Bot):
|
||||||
|
"""Adds function to bot"""
|
||||||
|
bot.add_cog(SubmissionListener(bot))
|
||||||
|
|
||||||
|
|
||||||
|
async def birthday_action(message: nextcord.Message) -> None:
|
||||||
|
"""
|
||||||
|
Checks a message's auther and mentions to see if they are in the birthday list.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message (nextcord.Message): The message to check for a birthday person.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if message.author.id in birthday_list or bool(set(message.raw_mentions) & set(birthday_list)):
|
||||||
|
await message.add_reaction("🎂")
|
||||||
@@ -31,6 +31,9 @@ class ElectionCycle:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
election_start: str
|
election_start: str
|
||||||
|
highcouncil_election_announce: str
|
||||||
|
highcouncil_election_end: str
|
||||||
|
highcouncil_election_start: str
|
||||||
name: str
|
name: str
|
||||||
term_end: str
|
term_end: str
|
||||||
term_start: str
|
term_start: str
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ from config import DakinyConfig
|
|||||||
cs = ConfigStore.instance()
|
cs = ConfigStore.instance()
|
||||||
cs.store(name="dakiny_config", node=DakinyConfig)
|
cs.store(name="dakiny_config", node=DakinyConfig)
|
||||||
|
|
||||||
|
birthday_list: list[int] = []
|
||||||
|
|
||||||
logger = logging.getLogger("nextcord")
|
logger = logging.getLogger("nextcord")
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
handler = logging.FileHandler(filename="nextcord.log", encoding="utf-8", mode="w")
|
handler = logging.FileHandler(filename="nextcord.log", encoding="utf-8", mode="w")
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ Base.prepare(autoload_with=engine)
|
|||||||
ElectionInformation = Base.classes.ElectionInformation
|
ElectionInformation = Base.classes.ElectionInformation
|
||||||
CouncilMembers = Base.classes.CouncilMembers
|
CouncilMembers = Base.classes.CouncilMembers
|
||||||
Votes = Base.classes.Votes
|
Votes = Base.classes.Votes
|
||||||
|
UserBirthday = Base.classes.UserBirthday
|
||||||
|
|||||||
Reference in New Issue
Block a user