Skip to content

Commit

Permalink
Merge pull request #3095 from freelawproject/fix-send-oa-alerts-after…
Browse files Browse the repository at this point in the history
…-file-is-processed

Fix, send OA alerts after MP3 file processing is completed.
  • Loading branch information
mlissner authored Sep 11, 2023
2 parents 5b47492 + 864d51e commit d92e6f1
Show file tree
Hide file tree
Showing 15 changed files with 442 additions and 72 deletions.
32 changes: 31 additions & 1 deletion cl/alerts/management/commands/cl_send_scheduled_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import DefaultDict

import waffle
from django.http import QueryDict
from django.utils.timezone import now

from cl.alerts.models import (
Expand All @@ -11,8 +12,9 @@
ScheduledAlertHit,
)
from cl.alerts.tasks import send_search_alert_emails
from cl.alerts.utils import InvalidDateError
from cl.alerts.utils import InvalidDateError, override_alert_query
from cl.lib.command_utils import VerboseCommand, logger
from cl.search.models import SEARCH_TYPES
from cl.stats.utils import tally_stat

DAYS_TO_DELETE = 90
Expand All @@ -28,6 +30,28 @@ def json_date_parser(dct):
return dct


def get_cut_off_date(rate: str, d: datetime.date) -> datetime.date | None:
"""Given a rate of dly, wly or mly and a date, returns the date after for
building a daterange filter.
:param rate: The alert rate to send Alerts.
:param d: The date alerts are run.
:return: The cut-off date or None.
"""
cut_off_date = None
if rate == Alert.DAILY:
cut_off_date = d
elif rate == Alert.WEEKLY:
cut_off_date = d - datetime.timedelta(days=7)
elif rate == Alert.MONTHLY:
# Get the first of the month of the previous month regardless of the
# current date
early_last_month = d - datetime.timedelta(days=28)
cut_off_date = datetime.datetime(
early_last_month.year, early_last_month.month, 1
).date()
return cut_off_date


def query_and_send_alerts_by_rate(rate: str) -> None:
"""Query and send alerts per user.
Expand Down Expand Up @@ -62,6 +86,12 @@ def query_and_send_alerts_by_rate(rate: str) -> None:
documents.append(json_date_parser(result.document_content))

alerts_to_update.append(alert.pk)

# Override order_by to show the latest items when clicking the
# "View Full Results" button.
cut_off_date = get_cut_off_date(rate, now_time.date())
qd = override_alert_query(alert, cut_off_date)
alert.query_run = qd.urlencode() # type: ignore
hits.append(
(
alert,
Expand Down
29 changes: 24 additions & 5 deletions cl/alerts/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
)

from cl.alerts.models import Alert, DocketAlert, ScheduledAlertHit
from cl.alerts.utils import percolate_document, user_has_donated_enough
from cl.alerts.utils import (
alert_hits_limit_reached,
override_alert_query,
percolate_document,
user_has_donated_enough,
)
from cl.api.models import WebhookEventType
from cl.api.tasks import (
send_docket_alert_webhook_events,
Expand All @@ -33,9 +38,9 @@
from cl.recap.constants import COURT_TIMEZONES
from cl.search.constants import ALERTS_HL_TAG
from cl.search.documents import AudioPercolator
from cl.search.models import Docket, DocketEntry
from cl.search.models import SEARCH_TYPES, Docket, DocketEntry
from cl.search.types import (
ESDocumentType,
ESDocumentClassType,
PercolatorResponseType,
SaveDocumentResponseType,
SearchAlertHitType,
Expand Down Expand Up @@ -477,7 +482,10 @@ def send_search_alert_emails(
continue

alert_user: UserProfile.user = User.objects.get(pk=user_id)
context = {"hits": hits}
context = {
"hits": hits,
"hits_limit": settings.SCHEDULED_ALERT_HITS_LIMIT,
}
txt = txt_template.render(context)
html = html_template.render(context)
msg = EmailMultiAlternatives(
Expand Down Expand Up @@ -527,6 +535,11 @@ def process_percolator_response(response: PercolatorResponseType) -> None:
ALERTS_HL_TAG,
)

# Override order_by to show the latest items when clicking the
# "View Full Results" button.
qd = override_alert_query(alert_triggered)
alert_triggered.query_run = qd.urlencode() # type: ignore

# Compose RT hit to send.
hits = [
(
Expand Down Expand Up @@ -554,6 +567,12 @@ def process_percolator_response(response: PercolatorResponseType) -> None:

else:
# Schedule DAILY, WEEKLY and MONTHLY Alerts
if alert_hits_limit_reached(
alert_triggered.pk, alert_triggered.user.pk
):
# Skip storing hits for this alert-user combination because
# the SCHEDULED_ALERT_HITS_LIMIT has been reached.
continue
scheduled_hits_to_create.append(
ScheduledAlertHit(
user=alert_triggered.user,
Expand Down Expand Up @@ -690,7 +709,7 @@ def index_alert_document(
ignore_result=True,
)
def remove_doc_from_es_index(
self: Task, es_document: ESDocumentType, instance_id: int
self: Task, es_document: ESDocumentClassType, instance_id: int
) -> None:
"""Remove a document from an Elasticsearch index.
Expand Down
4 changes: 2 additions & 2 deletions cl/alerts/templates/alert_email_es.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ <h1 class="bottom" style="font-size: 3em; font-weight: normal; line-height: 1;
{% for result in results %}
{% if forloop.first %}
<h2 style="font-size: 2em; font-weight: normal; font-family: inherit; color: #111; border: 0; vertical-align: baseline; font-style: inherit; margin: 0; padding: 0;" class="alt bottom">
Your {{alert.get_rate_display|lower}} {% if type == 'o' %}opinion{% elif type == 'oa' %}oral argument{% endif %} alert &mdash; {{alert.name}} &mdash; had {{num_results}} hit{{results|pluralize}}:
Your {{alert.get_rate_display|lower}} {% if type == 'o' %}opinion{% elif type == 'oa' %}oral argument{% endif %} alert &mdash; {{alert.name}} &mdash; had {{num_results}}{% if num_results >= hits_limit %}+{% endif %} hit{{results|pluralize}}:
</h2>
<p style="font-size: 100%; font-weight: inherit; font-family: inherit; border: 0; vertical-align: baseline; font-style: inherit; margin: 0 0 1.5em; padding: 0;">
<a href="https://www.courtlistener.com/?{{ alert.query|safe }}&edit_alert={{ alert.pk }}">View Full Results / Edit this Alert</a><br>
<a href="https://www.courtlistener.com/?{{ alert.query_run|safe }}&edit_alert={{ alert.pk }}">View Full Results / Edit this Alert</a><br>
<a href="https://www.courtlistener.com{% url "disable_alert" alert.secret_key %}">Disable this Alert (one click)</a>
</p>
{% endif %}
Expand Down
4 changes: 2 additions & 2 deletions cl/alerts/templates/alert_email_es.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ CourtListener.com
We have news regarding your alerts at CourtListener.com
-------------------------------------------------------

{% for alert, type, results, num_results in hits %}{% for result in results %}{% if forloop.first %}Your {{alert.get_rate_display|lower}} {% if type == 'o' %}opinion{% elif type == 'oa' %}oral argument{% endif %} alert -- {{alert.name}} -- had {{num_results}} hit{{results|pluralize}}:
{% for alert, type, results, num_results in hits %}{% for result in results %}{% if forloop.first %}Your {{alert.get_rate_display|lower}} {% if type == 'o' %}opinion{% elif type == 'oa' %}oral argument{% endif %} alert -- {{alert.name}} -- had {{num_results}}{% if num_results >= hits_limit %}+{% endif %} hit{{results|pluralize}}:
-------------------------------------------------------
Edit / Delete this Alert: https://www.courtlistener.com/alert/edit/{{ alert.pk }}/
View Full Results / Edit this Alert: https://www.courtlistener.com/?{{ alert.query_run|safe }}&edit_alert={{ alert.pk }}/
Disable this Alert (one click): https://www.courtlistener.com{% url "disable_alert" alert.secret_key %}{% endif %}

{{forloop.counter}}. {{ result.caseName|safe|striptags }} ({% if result.court_id != 'scotus' %}{{ result.court_citation_string|striptags }} {% endif %}{% if type == 'o' %}{{ result.dateFiled|date:"Y" }}{% elif type == 'oa' %}{{ result.dateArgued|date:"Y" }}{% endif %})
Expand Down
Loading

0 comments on commit d92e6f1

Please sign in to comment.