Compare commits

..

4 Commits

Author SHA1 Message Date
5e6e40f576 📧 Sending emails 2024-08-29 10:50:19 +02:00
7edba24b51 📝 Commenting imports 2024-08-29 10:36:00 +02:00
37702b7380 📝 Functions and docstrings 2024-08-29 10:30:06 +02:00
c42cf9cb1e 🗃️ Trello Card fetcher 2024-08-21 13:46:45 +02:00
3 changed files with 190 additions and 18 deletions

View File

@ -1,7 +1,10 @@
[Trello] [Trello]
TrelloAPIKey= APIKey=
APIToken=
BoardID=
[SMTP] [SMTP]
Server= Server=
Port=
Username= Username=
Password= Password=

202
main.py
View File

@ -1,5 +1,13 @@
from configparser import ConfigParser from configparser import ConfigParser # For reading the config.ini file
from shutil import copy from shutil import copy # For creating a new config.ini file
from requests import request # For using the Trello API
import smtplib, ssl, email # For sending emails
### Constants
TRELLO_API_CARDS_URL = "https://api.trello.com/1/boards/{id}/cards"
###
# TODO: Set up actual logging # TODO: Set up actual logging
def log(text: str): def log(text: str):
@ -7,8 +15,13 @@ def log(text: str):
def read_config() -> dict: def read_config() -> dict:
""" """
Returns the contents of config.ini as a a dict, assuming it exists and has Reads the file config.ini. If the there is no file, it will create one. If
no empty fields. the file has empty fields, it will notify the user and end the program.
RETURNS
-------
- dict
The contents of the config.ini file.
""" """
config = ConfigParser() config = ConfigParser()
@ -36,28 +49,183 @@ def read_config() -> dict:
return config_dict return config_dict
def get_trello_cards(config: dict) -> list[dict]:
"""
Uses the Trello API to get every card from the board, and extracts the important information.
PARAMETERS
----------
- config: dict
The config file data. Uses this for the board ID, and the API key and
token.
RETURNS
-------
- list[dict]
A list of each card, with the following information: card id, name of the card, when the last activity on the card was performed, the IDs of whatever members are assigned, and the labels the card has.
"""
url = TRELLO_API_CARDS_URL.format(id=config["Trello"]["boardid"])
query = {
'key': config["Trello"]["apikey"],
'token': config["Trello"]["apitoken"]
}
# Calling the API
response = request(
"GET",
url,
params=query
)
# Making a list of cards with relevant information
cards = [
{
"id": card["id"],
"name": card["name"],
"lastActivity": card["dateLastActivity"],
"memberIDs": card["idMembers"],
"labels": [label["name"] for label in card["labels"]]
}
for card in response.json()
]
return cards
def flag_out_of_date_cards(cards: list[dict]) -> list[dict]:
"""
Flags cards as out of date, if they exceed the deadline.
PARAMETERS
----------
- cards: list[dict]
The list of cards.
RETURNS
-------
- list[dict]
The same list of cards, but with an out_of_date boolean field.
"""
pass
def generate_reports(cards: list[dict]) -> tuple[str,list]:
"""
Generates the PDF reports for each user. Each report will be found at
./reports/TIMESTAMP/USERID.pdf
PARAMETERS
----------
- cards: list[dict]
The list of cards.
RETURNS
-------
- str
The timestamp used for the folder in which the reports are generated.
- list
The list of users reports were generated for.
"""
pass
def get_emails(config: dict, user_ids: list[str]) -> dict:
"""
Uses the Trello API to find the email addresses of the given users.
PARAMETERS
----------
- config: dict
The config file data. Uses this for the board ID, and the API key and
token.
- user_ids: list[str]
A list of user IDs.
RETURNS
-------
- dict
A dict where each user ID is the key and the value is their email.
"""
pass
def send_emails(config: dict, users: dict, timestamp: str) -> None:
"""
Sending out emails.
PARAMETERS
----------
- config: dict
The config file data. Uses this for the SMTP server, port, username,
and password.
- users: dict
Each user ID and the email connected to it.
- timestamp: str
The timestamp used to create the folder that the reports are in.
"""
# Create a secure SSL context
context = ssl.create_default_context()
# Logging in
server_url = config["SMTP"]["server"]
port = config["SMTP"]["port"]
username = config["SMTP"]["username"]
password = config["SMTP"]["password"]
with smtplib.SMTP_SSL(server_url, port, context=context) as server:
server.login(username, password)
# Looping through each user and sending them an email with the pdf
for user_id, receiver in users.items():
pdf_path = f"reports/{timestamp}/{user_id}.pdf"
subject = "Trello Report"
body = "Here is your Trello Report"
# Preparing the message
message = email.mime.multipart.MIMEMultipart()
message["From"] = username
message["To"] = receiver
message["Subject"] = subject
message.attach(email.mime.text.MIMEText(body, "plain"))
# Open PDF file in binary mode, and attach it to the email
with open(pdf_path, "rb") as file_pointer:
part = email.mime.base.MIMEBase("application", "octet-stream")
part.set_payload(file_pointer.read())
# Encode file in ASCII characters to send by email
email.encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= TrelloReport-{user_id}-{timestamp}.pdf",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
server.sendmail(username, receiver, text)
def main(): def main():
# Reading the config file # Reading the config file
config = read_config() config = read_config()
# Step 2: # Getting the cards from Trello
# Get data from Trello API cards = get_trello_cards(config)
# - Time each card has been in the step it's in
# - Escalation level
# - Who is assigned (as well as their email)
# Step 3: # Flagging the cards if they've exceeded their deadline
# For each card, compare to escalation rules to see if it's at the step cards = flag_out_of_date_cards(cards)
# and escalation level it should be at. If not, flag it.
# Step 4: # Generate the PDF reports
# Generate reports for each person, showing their own cards. timestamp, user_ids = generate_reports(cards)
# Perhaps a "master report" with every card.
# Step 5: # Get the email address of each user
# Send out the reports via email. users = get_emails(config, user_ids)
# Send out the emails
send_emails(config, users, timestamp)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
requests==2.32.3