Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c76e6806c | ||
|
|
5cb9be7e37 | ||
|
|
d573595114 | ||
|
|
7bded4aa57 | ||
|
|
a6c6a80f8f | ||
|
|
a52979a847 | ||
|
|
8eae82536e | ||
|
|
e5e638edc9 | ||
|
|
fc9eb7b151 | ||
|
|
1cb16d5a39 |
@@ -139,3 +139,4 @@ TODO.txt
|
|||||||
sql_tester.py
|
sql_tester.py
|
||||||
conf
|
conf
|
||||||
outputs
|
outputs
|
||||||
|
dakiny.db
|
||||||
+51
-25
@@ -6,8 +6,11 @@ from datetime import datetime, timedelta
|
|||||||
|
|
||||||
import nextcord
|
import nextcord
|
||||||
from nextcord.ext import commands
|
from nextcord.ext import commands
|
||||||
|
from sqlalchemy import select
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
|
from database.sql_data_classes import ElectionInformation, engine
|
||||||
from utils import get_datetime
|
from utils import get_datetime
|
||||||
|
|
||||||
|
|
||||||
@@ -17,7 +20,7 @@ class ElectionCycle:
|
|||||||
the cycle.
|
the cycle.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cycle: int, bot) -> None:
|
def __init__(self, cycle: int, bot: commands.Bot) -> None:
|
||||||
"""
|
"""
|
||||||
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.
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ class ElectionCycle:
|
|||||||
self.highcouncil_election_announce: datetime = self.voting_end + timedelta(days=1)
|
self.highcouncil_election_announce: datetime = self.voting_end + timedelta(days=1)
|
||||||
self.highcouncil_election_start: datetime = self.highcouncil_election_announce + timedelta(days=3)
|
self.highcouncil_election_start: datetime = self.highcouncil_election_announce + timedelta(days=3)
|
||||||
self.highcouncil_election_end: datetime = self.term_start - timedelta(days=1)
|
self.highcouncil_election_end: datetime = self.term_start - timedelta(days=1)
|
||||||
self.bot: commands.Bot = bot
|
self.guild: nextcord.Guild = bot.get_guild(self.config.params.guild_id)
|
||||||
|
|
||||||
def build_election_announcement(self) -> list[str]:
|
def build_election_announcement(self) -> list[str]:
|
||||||
"""
|
"""
|
||||||
@@ -68,7 +71,7 @@ class ElectionCycle:
|
|||||||
|
|
||||||
return message.split("---message_break---")
|
return message.split("---message_break---")
|
||||||
|
|
||||||
def build_highcouncil_election(self) -> str:
|
def build_highcouncil_election_announce(self) -> str:
|
||||||
"""
|
"""
|
||||||
Builds message to announce highcouncil election start.
|
Builds message to announce highcouncil election start.
|
||||||
|
|
||||||
@@ -79,7 +82,13 @@ class ElectionCycle:
|
|||||||
with open("bot_messages/highcouncil_election.txt", mode="r", encoding="utf8") as file:
|
with open("bot_messages/highcouncil_election.txt", mode="r", encoding="utf8") as file:
|
||||||
message = file.read()
|
message = file.read()
|
||||||
|
|
||||||
return message.format()
|
return message.format(
|
||||||
|
clan_council_elect_role_id=self.config.params.clan_council_elect_role_id,
|
||||||
|
highcouncil_election_announce=self.highcouncil_election_announce.strftime("%B %d"),
|
||||||
|
highcouncil_election_start=self.highcouncil_election_start.strftime("%B %d"),
|
||||||
|
highcouncil_election_end=self.highcouncil_election_end.strftime("%B %d"),
|
||||||
|
term_start_date=self.term_start.strftime("%B %d"),
|
||||||
|
)
|
||||||
|
|
||||||
def build_vote_start(self) -> str:
|
def build_vote_start(self) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -105,7 +114,6 @@ class ElectionCycle:
|
|||||||
Function checks current date to see if something needs to be run.
|
Function checks current date to see if something needs to be run.
|
||||||
"""
|
"""
|
||||||
today = datetime.today()
|
today = datetime.today()
|
||||||
print("checking the date")
|
|
||||||
|
|
||||||
# check all dates if action is needed
|
# check all dates if action is needed
|
||||||
if today.date() == self.election_start.date():
|
if today.date() == self.election_start.date():
|
||||||
@@ -120,63 +128,81 @@ class ElectionCycle:
|
|||||||
await self.term_start_action()
|
await self.term_start_action()
|
||||||
elif today.date() == self.term_end.date():
|
elif today.date() == self.term_end.date():
|
||||||
await self.term_end_action()
|
await self.term_end_action()
|
||||||
else:
|
|
||||||
print("today was not a special date")
|
|
||||||
print(today)
|
|
||||||
|
|
||||||
async def election_start_action(self) -> None:
|
async def election_start_action(self) -> None:
|
||||||
"""
|
"""
|
||||||
Performs required actions for when the election cycle starts.
|
Performs required actions for when the election cycle starts.
|
||||||
"""
|
"""
|
||||||
print("election cycle has started")
|
|
||||||
# create new channel for election
|
# create new channel for election
|
||||||
category: nextcord.CategoryChannel = self.bot.get_channel(self.config.params.active_category_id)
|
category: nextcord.CategoryChannel = self.guild.get_channel(self.config.params.active_category_id)
|
||||||
quarter_name: str = str(datetime.today().year) + "-" + self.elecion_cycle.name + "-election"
|
quarter_name: str = self.get_election_cycle_name()
|
||||||
# TODO need to store this id in the sqlite database
|
|
||||||
|
# create new entry into database.
|
||||||
election_channel = await category.create_text_channel(quarter_name)
|
election_channel = await category.create_text_channel(quarter_name)
|
||||||
|
with Session(engine) as session:
|
||||||
|
new_cycle = ElectionInformation(ElectionCycle=quarter_name, ElectionChannel=election_channel.id)
|
||||||
|
session.add(new_cycle)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
# post message announcing election
|
# post message announcing election
|
||||||
# election start message is returned as an array of string because it is too long. send each string
|
# election start message is returned as an array of string because it is too long. send each string
|
||||||
# individually.
|
# individually.
|
||||||
messages = self.build_election_announcement()
|
messages = self.build_election_announcement()
|
||||||
|
|
||||||
for message in messages:
|
for message in messages:
|
||||||
await election_channel.send(message)
|
await election_channel.send(message)
|
||||||
|
|
||||||
async def voting_start_action(self) -> None:
|
async def voting_start_action(self) -> None:
|
||||||
"""
|
"""
|
||||||
Performs required actions for when voting for candidates starts.
|
Sends message informing members that voting has started.
|
||||||
|
Removes write permission from the general clan member role.
|
||||||
|
Adds the voting emote to all messages not sent by the vote. (This is temporary until voting is managed.)
|
||||||
"""
|
"""
|
||||||
print("Voting has started")
|
message = self.build_vote_start()
|
||||||
await self.message_me("Voting has started")
|
clan_member_role: nextcord.Role = self.guild.get_role(self.config.params.clan_member_role_id)
|
||||||
|
with Session(engine) as session:
|
||||||
|
stmt = select(ElectionInformation).where(
|
||||||
|
ElectionInformation.ElectionCycle == self.get_election_cycle_name()
|
||||||
|
)
|
||||||
|
election_info = session.scalar(stmt)
|
||||||
|
election_channel = self.guild.get_channel(election_info.ElectionChannel)
|
||||||
|
await election_channel.send(message)
|
||||||
|
await election_channel.set_permissions(clan_member_role, send_messages=False)
|
||||||
|
|
||||||
async def voting_end_action(self) -> None:
|
async def voting_end_action(self) -> None:
|
||||||
"""
|
"""
|
||||||
Performs required actions for when voting time has ended.
|
Performs required actions for when voting time has ended.
|
||||||
"""
|
"""
|
||||||
print("voting has ended")
|
message = self.build_highcouncil_election_announce()
|
||||||
await self.message_me("voting has ended")
|
council_elect_role: nextcord.Role = self.guild.get_role(self.config.params.clan_council_elect_role_id)
|
||||||
|
with Session(engine) as session:
|
||||||
|
stmt = select(ElectionInformation).where(
|
||||||
|
ElectionInformation.ElectionCycle == self.get_election_cycle_name()
|
||||||
|
)
|
||||||
|
election_info = session.scalar(stmt)
|
||||||
|
election_channel = self.guild.get_channel(election_info.ElectionChannel)
|
||||||
|
await election_channel.send(message)
|
||||||
|
await election_channel.set_permissions(council_elect_role, send_messages=True)
|
||||||
|
|
||||||
async def highcouncil_election_action(self) -> None:
|
async def highcouncil_election_action(self) -> None:
|
||||||
"""
|
"""
|
||||||
Performs required actions for when the highcouncil is elected.
|
Performs required actions for when the highcouncil is elected.
|
||||||
"""
|
"""
|
||||||
print("Highcouncil election has started.")
|
print("Highcouncil election has started.")
|
||||||
await self.message_me("Highcouncil election has started.")
|
|
||||||
|
|
||||||
async def term_start_action(self) -> None:
|
async def term_start_action(self) -> None:
|
||||||
msg: str = "the term has started"
|
msg: str = "the term has started"
|
||||||
print(msg)
|
print(msg)
|
||||||
self.message_me(msg)
|
|
||||||
|
|
||||||
async def term_end_action(self):
|
async def term_end_action(self):
|
||||||
msg: str = "the term has ended"
|
msg: str = "the term has ended"
|
||||||
print(msg)
|
print(msg)
|
||||||
self.message_me(msg)
|
|
||||||
|
|
||||||
async def message_me(self, msg: str):
|
def get_election_cycle_name(self) -> str:
|
||||||
"""
|
"""
|
||||||
message a string to me
|
Builds the unique name of the current election cycle
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: the name of the election cycle
|
||||||
"""
|
"""
|
||||||
imcompiling: nextcord.User = await self.bot.fetch_user(206602713511886849)
|
|
||||||
await imcompiling.send(msg)
|
return f"{self.election_start.year} {self.elecion_cycle.name} election"
|
||||||
|
|||||||
@@ -53,3 +53,14 @@ class TestCog(commands.Cog, name="Test commands."):
|
|||||||
|
|
||||||
cycle = ElectionCycle(0, self.bot)
|
cycle = ElectionCycle(0, self.bot)
|
||||||
await cycle.election_start_action()
|
await cycle.election_start_action()
|
||||||
|
|
||||||
|
@test.subcommand()
|
||||||
|
async def voting_start(self, interaction: nextcord.Interaction):
|
||||||
|
"""
|
||||||
|
tests the voting start action
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (nextcord.Interaction): _description_
|
||||||
|
"""
|
||||||
|
cycle = ElectionCycle(0, self.bot)
|
||||||
|
await cycle.voting_start_action()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Params:
|
|||||||
clan_info_channel_id: int
|
clan_info_channel_id: int
|
||||||
clan_member_role_id: int
|
clan_member_role_id: int
|
||||||
discord_token: str
|
discord_token: str
|
||||||
|
guild_id: int
|
||||||
high_council_role_id: int
|
high_council_role_id: int
|
||||||
voting_emote_id: str
|
voting_emote_id: str
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import nextcord
|
|||||||
from hydra.core.config_store import ConfigStore
|
from hydra.core.config_store import ConfigStore
|
||||||
from nextcord.ext import commands
|
from nextcord.ext import commands
|
||||||
|
|
||||||
|
import database.create_database as create_database
|
||||||
from config import DakinyConfig
|
from config import DakinyConfig
|
||||||
|
|
||||||
cs = ConfigStore.instance()
|
cs = ConfigStore.instance()
|
||||||
@@ -38,6 +39,7 @@ def main(cfg: DakinyConfig):
|
|||||||
async def on_ready():
|
async def on_ready():
|
||||||
"""When Discord is connected"""
|
"""When Discord is connected"""
|
||||||
assert bot.user is not None
|
assert bot.user is not None
|
||||||
|
create_database # pylint: disable=pointless-statement
|
||||||
print(f"{bot.user.name} has connected to Discord!")
|
print(f"{bot.user.name} has connected to Discord!")
|
||||||
|
|
||||||
# Run Discord bot
|
# Run Discord bot
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Small script to create the database if it doesn't already exist.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
from os.path import exists
|
||||||
|
|
||||||
|
if not exists("dakiny.db"):
|
||||||
|
with sqlite3.connect("dakiny.db") as con:
|
||||||
|
cur = con.cursor()
|
||||||
|
|
||||||
|
with open("database/database.sql", mode="r", encoding="utf-8") as file:
|
||||||
|
database_script = file.read()
|
||||||
|
cur.executescript(database_script)
|
||||||
|
con.commit()
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
-- CREATE DATABASE dakiny;
|
||||||
|
-- use dakiny;
|
||||||
|
|
||||||
|
CREATE TABLE ElectionInformation(
|
||||||
|
ElectionCycle varchar(30) not null unique,
|
||||||
|
ElectionChannel bigint unsigned not null,
|
||||||
|
PRIMARY KEY (ElectionCycle)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE CouncilMembers(
|
||||||
|
ElectionCycle varchar(30) not null unique,
|
||||||
|
MemberId bigint unsigned not null,
|
||||||
|
Elected boolean DEFAULT false,
|
||||||
|
HighCouncilElect boolean DEFAULT false,
|
||||||
|
DiscordManager boolean DEFAULT false,
|
||||||
|
ClanLeader boolean DEFAULT false,
|
||||||
|
FOREIGN KEY (ElectionCycle) REFERENCES ElectionInformation(ElectionCycle),
|
||||||
|
PRIMARY KEY (ElectionCycle, MemberId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Votes(
|
||||||
|
ElectionCycle varchar(30) not null unique,
|
||||||
|
VoterId bigint unsigned not null,
|
||||||
|
VotedForId bigint unsigned not null,
|
||||||
|
FOREIGN KEY (ElectionCycle) REFERENCES ElectionInformation(ElectionCycle),
|
||||||
|
PRIMARY KEY (ElectionCycle, VoterId)
|
||||||
|
);
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
Simple file to set up the sqlalchemy connection to database.
|
||||||
|
"""
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.ext.automap import automap_base
|
||||||
|
|
||||||
|
# connect with sql alchemy and autoload schema
|
||||||
|
URL = "sqlite+pysqlite:///dakiny.db"
|
||||||
|
engine = create_engine(URL)
|
||||||
|
Base = automap_base()
|
||||||
|
Base.prepare(autoload_with=engine)
|
||||||
|
|
||||||
|
# define the classes
|
||||||
|
ElectionInformation = Base.classes.ElectionInformation
|
||||||
|
CouncilMembers = Base.classes.CouncilMembers
|
||||||
|
Votes = Base.classes.Votes
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
Discord permissions required for bot to operate:
|
Discord permissions required for bot to operate:
|
||||||
|
|
||||||
manage channels
|
manage channels
|
||||||
|
manage roles
|
||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
nextcord==2.4.2
|
nextcord==2.4.2
|
||||||
python-dotenv==1.0.0
|
python-dotenv==1.0.0
|
||||||
pytz==2022.7.1
|
pytz==2022.7.1
|
||||||
hydra-core==1.3.2
|
hydra-core==1.3.2
|
||||||
|
sqlalchemy<2.0
|
||||||
Reference in New Issue
Block a user