Skip to content

Email for saved searches #1619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions learning_resources_search/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,17 @@ def source_description(self):
channel = self.source_channel()
if self.display_label:
return self.display_label
if channel:
if channel and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE:
return channel.title
return self.original_url_params()

def source_channel(self):
original_query_params = self.original_url_params()
channels_filtered = Channel.objects.filter(search_filter=original_query_params)
if channels_filtered.exists():
if (
channels_filtered.exists()
and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE
):
return channels_filtered.first()
return None

Expand Down
16 changes: 13 additions & 3 deletions learning_resources_search/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from learning_resources_search.indexing_api import (
get_reindexing_alias_name,
)
from learning_resources_search.models import PercolateQuery

pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("mocked_es")]

Expand Down Expand Up @@ -63,7 +64,9 @@ def test_percolate_query_unit_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "offered_by=mitx"
assert query.source_label() == "unit"
Expand Down Expand Up @@ -91,7 +94,9 @@ def test_percolate_query_topic_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "topic=Math"
assert query.source_label() == "topic"
Expand All @@ -118,7 +123,9 @@ def test_percolate_query_department_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "department=physics"
assert query.source_label() == "department"
Expand Down Expand Up @@ -196,6 +203,9 @@ def encode_params(oparams):
original_query=original_query,
query=original_query,
display_label=test_label,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE
if is_channel_query
else PercolateQuery.SEARCH_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == encode_params(original_query)
if not is_channel_query:
Expand Down
31 changes: 24 additions & 7 deletions learning_resources_search/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from opensearchpy.exceptions import NotFoundError, RequestError
from requests.models import PreparedRequest

from learning_resources.constants import LearningResourceType
from learning_resources.etl.constants import RESOURCE_FILE_ETL_SOURCES
from learning_resources.models import (
ContentFile,
Expand Down Expand Up @@ -167,7 +168,7 @@ def _infer_percolate_group(percolate_query):
elif key == "offered_by":
return LearningResourceOfferor.objects.get(code=val[0]).name
return val[0]
return None
return percolate_query.original_url_params()


def _infer_percolate_group_url(percolate_query):
Expand All @@ -181,6 +182,8 @@ def _infer_percolate_group_url(percolate_query):
query_string_params = {k: v for k, v in original_query.items() if v}
if "endpoint" in query_string_params:
query_string_params.pop("endpoint")
if "sortby" not in query_string_params:
query_string_params["sortby"] = "new"
query_string = urlencode(query_string_params, doseq=True)
return frontend_absolute_url(f"/search?{query_string}")

Expand Down Expand Up @@ -232,7 +235,9 @@ def _get_percolated_rows(resources, subscription_type):
"resource_image_url": resource.image.url
if resource.image
else "",
"resource_type": resource.resource_type,
"resource_type": LearningResourceType[
resource.resource_type
].value,
"user_id": user,
"source_label": query.source_label(),
"source_channel_type": source_channel.channel_type
Expand Down Expand Up @@ -881,23 +886,35 @@ def finish_recreate_index(results, backing_indices):
def _generate_subscription_digest_subject(
sample_course, source_name, unique_resource_types, total_count, shortform
):
prefix = "" if shortform else "MIT Learn: "
"""
Generate the subject line and/or content header for subscription emails
Args:
sample_course (a learning resource): A sample resource to reference
source_name (string): the subscription type (saved_search etc)
unique_resource_types (list): set of unique resource types in the email
total_count (int): total number of resources in the email
shortform (bool): if False return the (longer) email subject
otherwise short content header

"""
prefix = "" if shortform else "MIT Learn: "
resource_type = unique_resource_types.pop()
if sample_course["source_channel_type"] == "saved_search":
if shortform:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would this shortform be used? Would be helpful to add a dosctring to this function with Args and Returns sections

return f"New {resource_type}{pluralize(total_count)} from MIT Learn"
return (
f"{prefix}New"
f' "{source_name}" '
f"{unique_resource_types.pop().capitalize()}{pluralize(total_count)}"
f" {resource_type}{pluralize(total_count)}: "
f"{sample_course['resource_title']}"
)
preposition = "from"
if sample_course["source_channel_type"] == "topic":
preposition = "in"

suffix = "" if shortform else f": {sample_course['resource_title']}"

return (
f"{prefix}New"
f" {unique_resource_types.pop().capitalize()}{pluralize(total_count)} "
f" {resource_type}{pluralize(total_count)} "
f"{preposition} {source_name}{suffix}"
)

Expand Down
8 changes: 4 additions & 4 deletions learning_resources_search/tasks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ def test_subscription_digest_subject():
total_count=1,
shortform=False,
)
assert subject_line == "MIT Learn: New Program in electronics: robotics"
assert subject_line == "MIT Learn: New program in electronics: robotics"

sample_course = {"source_channel_type": "podcast", "resource_title": "robotics"}
resource_types = {"program"}
Expand All @@ -963,7 +963,7 @@ def test_subscription_digest_subject():
total_count=9,
shortform=False,
)
assert subject_line == "MIT Learn: New Programs from xpro: robotics"
assert subject_line == "MIT Learn: New programs from xpro: robotics"

resource_types = {"podcast"}
subject_line = _generate_subscription_digest_subject(
Expand All @@ -973,13 +973,13 @@ def test_subscription_digest_subject():
total_count=19,
shortform=False,
)
assert subject_line == "MIT Learn: New Podcasts from engineering: robotics"
assert subject_line == "MIT Learn: New podcasts from engineering: robotics"

resource_types = {"course"}
subject_line = _generate_subscription_digest_subject(
sample_course, "management", resource_types, 19, shortform=True
)
assert subject_line == "New Courses from management"
assert subject_line == "New courses from management"


def test_update_featured_rank(mocker, offeror_featured_lists):
Expand Down
5 changes: 5 additions & 0 deletions main/settings_celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
"schedule": crontab(minute=30, hour=18), # 2:30pm EST
"kwargs": {"period": "daily", "subscription_type": "channel_subscription_type"},
},
"send-search-subscription-emails-every-1-days": {
"task": "learning_resources_search.tasks.send_subscription_emails",
"schedule": crontab(minute=0, hour=19), # 3:00pm EST
"kwargs": {"period": "daily", "subscription_type": "search_subscription_type"},
},
"update-search-featured-ranks-1-days": {
"task": "learning_resources_search.tasks.update_featured_rank",
"schedule": crontab(minute=30, hour=7), # 3:30am EST
Expand Down
Loading