-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added mail_parser, notifier and notify command
- Loading branch information
Showing
9 changed files
with
258 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<html> | ||
|
||
<head> | ||
<style> | ||
/* ignore */ | ||
{% block style %} | ||
{% endblock %} | ||
/* ignore */ | ||
</style> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.16.22/dist/css/uikit.min.css" /> | ||
</head> | ||
|
||
<body> | ||
{% block content %}{% endblock %} | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{% extends "base.html" %} | ||
{% block style %} | ||
th, | ||
td { | ||
width: 25% text-align: center !important | ||
} | ||
{% endblock %} | ||
|
||
{% block content %} | ||
Project: {{ project.name }} | ||
<br /> | ||
Repo: <a href='{{ project.repo }}'>{{ project.repo }}</a> | ||
<br /> | ||
{% if is_outdated %} | ||
Your project is using some packages that are EOL. This means that they are no longer stable or supported and may have | ||
security vulnerabilities or compatibility problems. You should update them to the next LTS version immediately to fix | ||
these issues. Here is a list of the packages: | ||
{% else %} | ||
Your project is using some packages that will be EOL soon. You should consider updating them to the next LTS version as | ||
soon as possible to avoid potential issues. Here is a list of the packages that need updating: | ||
{% endif %} | ||
<br /> | ||
{% for vd in versioned_dependencies %} | ||
<br /> | ||
{{ vd.dependency }}: current LTS version <span class='uk-text-{{ "danger" if vd.is_EOL else "warning" }}'>{{ | ||
vd.version }}</span>, EOL {{vd.since_in_string}} days | ||
{% endfor %} | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import re | ||
from typing import Any, Union | ||
|
||
from django.core.mail import EmailMultiAlternatives | ||
from django.core.mail.message import EmailMessage | ||
from django.utils.html import strip_tags | ||
from jinja2 import Environment, FileSystemLoader, Template | ||
|
||
|
||
class EmailParser: | ||
"""Parse mail from template.""" | ||
|
||
def __init__( | ||
self, | ||
mail_kwargs: dict[str, Any], | ||
template: Union[str, Template], | ||
context: dict[str, Any], | ||
) -> None: | ||
self.mail_kwargs = mail_kwargs | ||
self.template = template | ||
self.context = context | ||
|
||
@staticmethod | ||
def _template_to_text(parsed_template: str) -> str: | ||
"""Parse the parsed templates html to raw text.""" | ||
|
||
cleaned_template = parsed_template.replace("\n", "").replace("<br />", "\n") | ||
|
||
text = strip_tags(cleaned_template) | ||
|
||
return re.sub( | ||
r"[/][*] ignore [*][/].*[/][*] ignore [*][/]", | ||
"", | ||
text, | ||
flags=re.DOTALL, | ||
).strip() | ||
|
||
def parse_mail(self) -> EmailMessage: | ||
"""Parse a MailMessage from the template.""" | ||
|
||
env = Environment(loader=FileSystemLoader("outdated/email-templates")) | ||
template = env.get_template(self.template) | ||
if not template: | ||
raise ValueError("Mail template does not exist!") | ||
body = template.render(**self.context) | ||
message = EmailMultiAlternatives( | ||
body=self._template_to_text(body), **self.mail_kwargs | ||
) | ||
message.attach_alternative(body, "text/html") | ||
return message |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from django.core.management.base import BaseCommand | ||
|
||
from outdated.outdated.models import Project | ||
from outdated.outdated.notifier import Notifier | ||
|
||
|
||
class Command(BaseCommand): | ||
help = "Sends email notification to maintainers when project outdated/warning" | ||
|
||
def handle(self, *args, **options): | ||
for project in Project.objects.all(): | ||
Notifier(project).send() | ||
print("Finished") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from datetime import date | ||
|
||
from outdated.email_parser import EmailParser | ||
from outdated.outdated import models | ||
|
||
|
||
class Notifier: | ||
"""Check project and send an informative mail if the status is outdated/warning.""" | ||
|
||
def __init__(self, project: models.Project) -> None: | ||
self.project = project | ||
|
||
def send(self): | ||
# maybe sync project before checking | ||
if not self.project.maintainers: | ||
return | ||
if self.project.status in ["UP_TO_DATE", "UNDEFINED"]: | ||
return | ||
|
||
dependencies = [ | ||
version | ||
for version in self.project.versioned_dependencies.all() | ||
if version.status in ["OUTDATED", "WARNING"] | ||
] | ||
is_outdated = self.project.status == "OUTDATED" | ||
|
||
subject = f"{'Your project is out of date!' if is_outdated else 'Your project will be out of date soon!'}" | ||
context = dict( | ||
versioned_dependencies=dependencies, | ||
project=self.project, | ||
is_outdated=is_outdated, | ||
today=date.today(), | ||
) | ||
email_kwargs = dict( | ||
subject=subject, | ||
to=[self.project.maintainers.get(is_primary=True).user.email], | ||
cc=[ | ||
maintainer.user.email | ||
for maintainer in self.project.maintainers.filter(is_primary=False) | ||
if is_outdated | ||
], | ||
) | ||
email = EmailParser(email_kwargs, "notification.html", context).parse_mail() | ||
return email.send() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.