Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fb59ba394 | ||
|
|
7b521893d3 | ||
|
|
19e654aed0 | ||
|
|
0d38bc82c4 | ||
|
|
b64e2471fa | ||
|
|
0b5330f7ca | ||
|
|
4e64eac176 | ||
|
|
c90ddf42c3 | ||
|
|
8eb2457ae9 | ||
|
|
2bdb7cb17b | ||
|
|
07906aaea1 | ||
|
|
9109ac53b3 | ||
|
|
47a33128be |
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"aiofiles",
|
||||||
|
"blurple",
|
||||||
|
"CLANLEADER",
|
||||||
|
"Dakiny",
|
||||||
|
"DISCORDMANAGER",
|
||||||
|
"highcouncil"
|
||||||
|
]
|
||||||
|
}
|
||||||
+84
-2
@@ -5,7 +5,7 @@ from discord import TextInputStyle
|
|||||||
from nextcord.ext import commands
|
from nextcord.ext import commands
|
||||||
|
|
||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
from utils import record_event_points
|
from utils import GUILDS, MAX_DISCORD_MESSAGE_LENGTH, record_event_points
|
||||||
|
|
||||||
|
|
||||||
class RecordCog(commands.Cog, name="Record Commands"):
|
class RecordCog(commands.Cog, name="Record Commands"):
|
||||||
@@ -16,7 +16,7 @@ class RecordCog(commands.Cog, name="Record Commands"):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.bot: commands.Bot = bot
|
self.bot: commands.Bot = bot
|
||||||
|
|
||||||
@nextcord.slash_command()
|
@nextcord.slash_command(guild_ids=GUILDS)
|
||||||
async def record(self, interaction: nextcord.Interaction) -> None:
|
async def record(self, interaction: nextcord.Interaction) -> None:
|
||||||
"""Parent slash command for record. Never called."""
|
"""Parent slash command for record. Never called."""
|
||||||
|
|
||||||
@@ -64,6 +64,88 @@ class RecordCog(commands.Cog, name="Record Commands"):
|
|||||||
embed=embed,
|
embed=embed,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@record.subcommand(description="Record a miscellaneous point for a clan member.")
|
||||||
|
async def point(
|
||||||
|
self,
|
||||||
|
interaction: nextcord.Interaction,
|
||||||
|
activity: str = nextcord.SlashOption(
|
||||||
|
description="The type of activity to receive points for.",
|
||||||
|
required=True,
|
||||||
|
choices=[
|
||||||
|
"Clan chat activity",
|
||||||
|
"Teaching or sharing in-game tips",
|
||||||
|
"Recruiting efforts",
|
||||||
|
"Successful recruitment",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
justification: str = nextcord.SlashOption(
|
||||||
|
required=True,
|
||||||
|
description="Reason to give the recipient a point.",
|
||||||
|
max_length=int(MAX_DISCORD_MESSAGE_LENGTH / 2),
|
||||||
|
),
|
||||||
|
recipient: nextcord.Member = nextcord.SlashOption(
|
||||||
|
required=False,
|
||||||
|
description="Discord user to give point to.",
|
||||||
|
),
|
||||||
|
non_discord_recipient: str = nextcord.SlashOption(
|
||||||
|
required=False, description="Non Discord user to give point to.", max_length=32
|
||||||
|
),
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Gives a point to the provided recipient. Sends recording message to event participation channel.
|
||||||
|
|
||||||
|
Only one recipient should be given point/provided to the command. Fails if not exactly one recipient
|
||||||
|
is given.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (nextcord.Interaction): interaction with this command.
|
||||||
|
activity (str): Choice list of activities to give point for.
|
||||||
|
justification (str): Reason to give point.
|
||||||
|
recipient (nextcord.Member): Discord member to give point to.
|
||||||
|
non_discord_recipient (str): Non Discord member to give point to.
|
||||||
|
"""
|
||||||
|
# role check
|
||||||
|
if interaction.guild.get_role(self.bot.config.params.clan_member_role_id) not in interaction.user.roles:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"You must have the <@&{self.bot.config.params.clan_member_role_id}> role to record points.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# pylint or whatever seems to think that there are lines of unreachable code. That is false.
|
||||||
|
if recipient and non_discord_recipient:
|
||||||
|
await interaction.response.send_message("Please only provide 1 recipient.", ephemeral=True)
|
||||||
|
return
|
||||||
|
elif recipient is not None: # noqa: RET505
|
||||||
|
record_event_points(
|
||||||
|
self.bot.config,
|
||||||
|
[str(recipient.id)],
|
||||||
|
self.bot.config.params.event_participate_points,
|
||||||
|
is_member=True,
|
||||||
|
)
|
||||||
|
recipient_str = f"<@{recipient.id}>"
|
||||||
|
elif non_discord_recipient is not None:
|
||||||
|
record_event_points(
|
||||||
|
self.bot.config,
|
||||||
|
[non_discord_recipient],
|
||||||
|
self.bot.config.params.event_participate_points,
|
||||||
|
is_member=False,
|
||||||
|
)
|
||||||
|
recipient_str = f'"{non_discord_recipient}"'
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("You must provide a recipient.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
event_channel: nextcord.TextChannel = interaction.guild.get_channel(
|
||||||
|
self.bot.config.params.event_post_channel_id
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = f"<@{interaction.user.id}> has given {recipient_str} points for the {activity} activity. Justification: {justification}" # noqa: E501
|
||||||
|
if not msg.endswith("."):
|
||||||
|
msg += "."
|
||||||
|
await event_channel.send(msg)
|
||||||
|
await interaction.response.send_message("Point has been added.", ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
class EventView(nextcord.ui.View):
|
class EventView(nextcord.ui.View):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+10
-8
@@ -7,7 +7,7 @@ from sqlalchemy import select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from database_setup.sql_data_classes import (
|
from database_setup.sql_data_classes import (
|
||||||
ParticipationPoints,
|
EventPoints,
|
||||||
Presences,
|
Presences,
|
||||||
Votes,
|
Votes,
|
||||||
engine,
|
engine,
|
||||||
@@ -49,14 +49,12 @@ class ViewCog(commands.Cog, name="View Commands"):
|
|||||||
with Session(engine) as session:
|
with Session(engine) as session:
|
||||||
if quarter_name:
|
if quarter_name:
|
||||||
ppdf = pd.read_sql_query(
|
ppdf = pd.read_sql_query(
|
||||||
sql=session.query(ParticipationPoints)
|
sql=session.query(EventPoints).where(EventPoints.Cycle.startswith(quarter_name)).statement,
|
||||||
.where(ParticipationPoints.Cycle.startswith(quarter_name))
|
|
||||||
.statement,
|
|
||||||
con=engine,
|
con=engine,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ppdf = pd.read_sql_query(
|
ppdf = pd.read_sql_query(
|
||||||
sql=session.query(ParticipationPoints).statement,
|
sql=session.query(EventPoints).statement,
|
||||||
con=engine,
|
con=engine,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -70,14 +68,18 @@ class ViewCog(commands.Cog, name="View Commands"):
|
|||||||
content += f"**{cycle}**\n"
|
content += f"**{cycle}**\n"
|
||||||
unsorted_all = cycles.get_group(cycle).groupby("DiscordMember")
|
unsorted_all = cycles.get_group(cycle).groupby("DiscordMember")
|
||||||
members = unsorted_all.get_group(name=True)
|
members = unsorted_all.get_group(name=True)
|
||||||
non_members = unsorted_all.get_group(name=False)
|
|
||||||
|
# there can be no non-discord members sometimes.
|
||||||
|
try:
|
||||||
|
sorted_non_members = unsorted_all.get_group(name=False).sort_values(by="UserId")
|
||||||
|
except KeyError:
|
||||||
|
sorted_non_members = None
|
||||||
sorted_members = members.sort_values(
|
sorted_members = members.sort_values(
|
||||||
by="UserId",
|
by="UserId",
|
||||||
key=lambda user_ids: (
|
key=lambda user_ids: (
|
||||||
[interaction.guild.get_member(int(user_id)).display_name.lower() for user_id in user_ids]
|
[interaction.guild.get_member(int(user_id)).display_name.lower() for user_id in user_ids]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
sorted_non_members = non_members.sort_values(by="UserId")
|
|
||||||
sorted_all = pd.concat([sorted_members, sorted_non_members], ignore_index=True, sort=False)
|
sorted_all = pd.concat([sorted_members, sorted_non_members], ignore_index=True, sort=False)
|
||||||
for row in sorted_all.itertuples():
|
for row in sorted_all.itertuples():
|
||||||
userid = row.UserId
|
userid = row.UserId
|
||||||
@@ -199,7 +201,7 @@ class ViewCog(commands.Cog, name="View Commands"):
|
|||||||
quarter_name (str): String to run autocomplete on.
|
quarter_name (str): String to run autocomplete on.
|
||||||
"""
|
"""
|
||||||
with Session(engine) as session:
|
with Session(engine) as session:
|
||||||
stmt = select(ParticipationPoints.Cycle).distinct()
|
stmt = select(EventPoints.Cycle).distinct()
|
||||||
quarters = session.scalars(stmt)
|
quarters = session.scalars(stmt)
|
||||||
|
|
||||||
# if empty compare string
|
# if empty compare string
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class DailyLoop(commands.Cog, name="Daily Loop"):
|
|||||||
|
|
||||||
# kandy's 1% chance
|
# kandy's 1% chance
|
||||||
if random.randint(0, 99) == 0: # noqa: S311 isn't cryptography related.
|
if random.randint(0, 99) == 0: # noqa: S311 isn't cryptography related.
|
||||||
birthday_list.append(239547993106284544)
|
birthday_list.append(KANDY)
|
||||||
|
|
||||||
today = datetime.now(tz=UTC).date()
|
today = datetime.now(tz=UTC).date()
|
||||||
birthday = f"{today.month}/{today.day}"
|
birthday = f"{today.month}/{today.day}"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ CREATE TABLE Presences (
|
|||||||
Presence varchar(100) not null
|
Presence varchar(100) not null
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE ParticipationPoints (
|
CREATE TABLE EventPoints (
|
||||||
Cycle varchar(30) not null,
|
Cycle varchar(30) not null,
|
||||||
UserId varchar(32) not null,
|
UserId varchar(32) not null,
|
||||||
DiscordMember boolean not null,
|
DiscordMember boolean not null,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ CouncilMembers = Base.classes.CouncilMembers
|
|||||||
ElectionInformation = Base.classes.ElectionInformation
|
ElectionInformation = Base.classes.ElectionInformation
|
||||||
EventPointsLimit = Base.classes.EventPointsLimit
|
EventPointsLimit = Base.classes.EventPointsLimit
|
||||||
Messages = Base.classes.Messages
|
Messages = Base.classes.Messages
|
||||||
ParticipationPoints = Base.classes.ParticipationPoints
|
EventPoints = Base.classes.EventPoints
|
||||||
Presences = Base.classes.Presences
|
Presences = Base.classes.Presences
|
||||||
UserBirthday = Base.classes.UserBirthday
|
UserBirthday = Base.classes.UserBirthday
|
||||||
Votes = Base.classes.Votes
|
Votes = Base.classes.Votes
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ setuptools = "^70.0.0"
|
|||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
ruff = "^0.4.5"
|
ruff = "^0.6.3"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ from sqlalchemy.orm import Session
|
|||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
from database_setup.sql_data_classes import (
|
from database_setup.sql_data_classes import (
|
||||||
CouncilMembers,
|
CouncilMembers,
|
||||||
|
EventPoints,
|
||||||
EventPointsLimit,
|
EventPointsLimit,
|
||||||
Messages,
|
Messages,
|
||||||
ParticipationPoints,
|
|
||||||
Votes,
|
Votes,
|
||||||
engine,
|
engine,
|
||||||
)
|
)
|
||||||
@@ -137,7 +137,7 @@ def build_votes_str(config: DakinyConfig, guild: nextcord.Guild) -> str:
|
|||||||
Creates a string that contains all nominees and their votes to be sent as a discord message.
|
Creates a string that contains all nominees and their votes to be sent as a discord message.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config (DakinyConfig): Daking config object
|
config (DakinyConfig): Dakiny config object
|
||||||
guild (nextcord.Guild): The guild object. Used to get display names for sorting.
|
guild (nextcord.Guild): The guild object. Used to get display names for sorting.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -173,7 +173,7 @@ def build_highcouncil_votes_str(config: DakinyConfig, guild: nextcord.Guild) ->
|
|||||||
Creates a string that contains all high council nominees and their votes to be sent as a discord message.
|
Creates a string that contains all high council nominees and their votes to be sent as a discord message.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config (DakinyConfig): Daking config object
|
config (DakinyConfig): Dakiny config object
|
||||||
guild (nextcord.Guild): The guild object. Used to get display names for sorting.
|
guild (nextcord.Guild): The guild object. Used to get display names for sorting.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -318,16 +318,12 @@ def record_event_points(config: DakinyConfig, users: Sequence[str], add_points:
|
|||||||
quarter_name = get_quarter_name(config)
|
quarter_name = get_quarter_name(config)
|
||||||
with Session(engine) as session:
|
with Session(engine) as session:
|
||||||
for user in users:
|
for user in users:
|
||||||
stmt = (
|
stmt = select(EventPoints).where(EventPoints.UserId == user).where(EventPoints.Cycle == quarter_name)
|
||||||
select(ParticipationPoints)
|
|
||||||
.where(ParticipationPoints.UserId == user)
|
|
||||||
.where(ParticipationPoints.Cycle == quarter_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
points = session.scalar(stmt)
|
points = session.scalar(stmt)
|
||||||
if points is None:
|
if points is None:
|
||||||
add_points = get_allowed_points(session, config.params.event_points_weekly_limit, user, add_points)
|
add_points = get_allowed_points(session, config.params.event_points_weekly_limit, user, add_points)
|
||||||
new_points = ParticipationPoints(
|
new_points = EventPoints(
|
||||||
Cycle=quarter_name,
|
Cycle=quarter_name,
|
||||||
UserId=user,
|
UserId=user,
|
||||||
DiscordMember=is_member,
|
DiscordMember=is_member,
|
||||||
@@ -371,11 +367,7 @@ def get_allowed_points(session: Session, points_limit: int, user: str, points: i
|
|||||||
add_points = points
|
add_points = points
|
||||||
session.add(new_limit)
|
session.add(new_limit)
|
||||||
else:
|
else:
|
||||||
add_points = (
|
add_points = points if limit.Points + points <= points_limit else (max(0, points_limit - limit.Points))
|
||||||
points
|
|
||||||
if limit.Points + points <= points_limit
|
|
||||||
else (points_limit - limit.Points if points_limit - limit.Points > 0 else 0)
|
|
||||||
)
|
|
||||||
limit.Points += add_points
|
limit.Points += add_points
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
@@ -512,7 +504,7 @@ async def edit_clan_message(
|
|||||||
|
|
||||||
async def edit_clan_council_info(guild: nextcord.Guild, config: DakinyConfig) -> None:
|
async def edit_clan_council_info(guild: nextcord.Guild, config: DakinyConfig) -> None:
|
||||||
"""
|
"""
|
||||||
Gets the winners of the elections and updates the perminant message that states the current council.
|
Gets the winners of the elections and updates the permanent message that states the current council.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
guild (nextcord.Guild): Guild object that to use to get channel.
|
guild (nextcord.Guild): Guild object that to use to get channel.
|
||||||
|
|||||||
Reference in New Issue
Block a user