prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Engagement bot thinks every user is a returning user
  ### Context
  
  https://alexslemonade.slack.com/archives/CRK42AL1Y/p1587988808265500
  
  ### Problem or idea
  
  @dvenprasad says 6 of those are new users. There must be a bug in the queries it uses or something.
  
  ### Solution or next step
  
  Fix the engagement bot so it reports new users as new users.
  
  </issue>
  <code>
  [start of api/data_refinery_api/management/commands/post_downloads_summary.py]
  1 import datetime
  2 
  3 from django.conf import settings
  4 from django.core.management.base import BaseCommand
  5 from django.utils import timezone
  6 
  7 import requests
  8 
  9 from data_refinery_common.models import DatasetAnnotation
  10 
  11 
  12 class Command(BaseCommand):
  13     help = "Post downloads summary to slack"
  14 
  15     def add_arguments(self, parser):
  16         parser.add_argument(
  17             "--days",
  18             type=int,
  19             default=7,  # default to a week
  20             help=("Number of days in the past for which to build the stats"),
  21         )
  22         parser.add_argument(
  23             "--channel",
  24             type=str,
  25             default="ccdl-general",
  26             help=("Optional parameter to choose the channel where the message will be posted."),
  27         )
  28 
  29     def handle(self, *args, **options):
  30         days = options["days"]
  31         start_time = timezone.now() - datetime.timedelta(days=days)
  32 
  33         annotation_queryset = DatasetAnnotation.objects.filter(
  34             created_at__gt=start_time
  35         ).prefetch_related("dataset")
  36         annotations = [
  37             annotation
  38             for annotation in annotation_queryset
  39             if annotation.data["start"] and should_display_email(annotation.dataset.email_address)
  40         ]
  41 
  42         unique_users = list(set(annotation.dataset.email_address for annotation in annotations))
  43         unique_ips = list(set(annotation.data["ip"] for annotation in annotations))
  44 
  45         if unique_users:
  46             fallback_text = "In the last {0} days, {1} users downloaded datasets from {2} locations.".format(
  47                 days, len(unique_users), len(unique_ips)
  48             )
  49         else:
  50             fallback_text = "There were no downloads in the last {0} days.".format(days)
  51 
  52         new_users = ""
  53         returning_users = ""
  54         for email in unique_users:
  55             user_annotations = annotation_queryset.filter(dataset__email_address=email)
  56             total_downloads = user_annotations.count()
  57             unique_locations = list(set(annotation.data["ip"] for annotation in user_annotations))
  58             locations = ", ".join(get_ip_location(ip) for ip in unique_locations)
  59             is_new_user = DatasetAnnotation.objects.filter(
  60                 created_at__lt=start_time, dataset__email_address=email
  61             )
  62             text = "{0} | {1} downloads from {2}\n".format(email, total_downloads, locations)
  63             if is_new_user:
  64                 new_users += text
  65             else:
  66                 returning_users += text
  67 
  68         blocks = [
  69             {
  70                 "type": "section",
  71                 "text": {"type": "plain_text", "emoji": True, "text": fallback_text},
  72             }
  73         ]
  74         if new_users:
  75             blocks.append(
  76                 {
  77                     "type": "section",
  78                     "text": {"type": "mrkdwn", "text": "*New users* \n" + new_users,},
  79                 }
  80             )
  81         if returning_users:
  82             blocks.append(
  83                 {
  84                     "type": "section",
  85                     "text": {"type": "mrkdwn", "text": "*Returning users* \n" + returning_users,},
  86                 }
  87             )
  88 
  89         # Post to slack
  90         requests.post(
  91             settings.ENGAGEMENTBOT_WEBHOOK,
  92             json={
  93                 "username": "EngagementBot",
  94                 "icon_emoji": ":halal:",
  95                 "channel": "#" + options["channel"],
  96                 "text": fallback_text,
  97                 "blocks": blocks,
  98             },
  99             headers={"Content-Type": "application/json"},
  100             timeout=10,
  101         )
  102 
  103 
  104 def should_display_email(email: str) -> bool:
  105     """ Returns true if the given email is not associated with the CCDL suers """
  106     if not email:
  107         return False
  108     return not (
  109         email.startswith("cansav09")
  110         or email.startswith("arielsvn")
  111         or email.startswith("jaclyn.n.taroni")
  112         or email.startswith("kurt.wheeler")
  113         or email.startswith("greenescientist")
  114         or email.startswith("miserlou")
  115         or email.startswith("d.prasad")
  116         or email.endswith("@alexslemonade.org")
  117         or email is ("daniel.himmelstein@gmail.com")
  118         or email is ("dv.prasad991@gmail.com")
  119     )
  120 
  121 
  122 def get_ip_location(remote_ip):
  123     try:
  124         data = requests.get("https://ipapi.co/" + remote_ip + "/json/", timeout=10).json()
  125         return "{0}, {1}".format(data["city"], data["country_name"])
  126     except Exception:
  127         return remote_ip
  128
  [end of api/data_refinery_api/management/commands/post_downloads_summary.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/api/data_refinery_api/management/commands/post_downloads_summary.py b/api/data_refinery_api/management/commands/post_downloads_summary.py
  --- a/api/data_refinery_api/management/commands/post_downloads_summary.py
  +++ b/api/data_refinery_api/management/commands/post_downloads_summary.py
  @@ -42,28 +42,30 @@
           unique_users = list(set(annotation.dataset.email_address for annotation in annotations))
           unique_ips = list(set(annotation.data["ip"] for annotation in annotations))
   
  -        if unique_users:
  -            fallback_text = "In the last {0} days, {1} users downloaded datasets from {2} locations.".format(
  -                days, len(unique_users), len(unique_ips)
  -            )
  -        else:
  -            fallback_text = "There were no downloads in the last {0} days.".format(days)
  -
           new_users = ""
           returning_users = ""
  +        total_downloads = 0
           for email in unique_users:
               user_annotations = annotation_queryset.filter(dataset__email_address=email)
  -            total_downloads = user_annotations.count()
  +            downloads = user_annotations.count()
  +            total_downloads += downloads
               unique_locations = list(set(annotation.data["ip"] for annotation in user_annotations))
               locations = ", ".join(get_ip_location(ip) for ip in unique_locations)
  -            is_new_user = DatasetAnnotation.objects.filter(
  +            is_returning_user = DatasetAnnotation.objects.filter(
                   created_at__lt=start_time, dataset__email_address=email
               )
  -            text = "{0} | {1} downloads from {2}\n".format(email, total_downloads, locations)
  -            if is_new_user:
  -                new_users += text
  -            else:
  +            text = "{0} | {1} downloads from {2}\n".format(email, downloads, locations)
  +            if is_returning_user:
                   returning_users += text
  +            else:
  +                new_users += text
  +
  +        if total_downloads > 0:
  +            fallback_text = "In the last {0} days, {1} users downloaded {2} datasets from {3} locations.".format(
  +                days, len(unique_users), total_downloads, len(unique_ips)
  +            )
  +        else:
  +            fallback_text = "There were no downloads in the last {0} days.".format(days)
   
           blocks = [
               {
  
verification_info: {"golden_diff": "diff --git a/api/data_refinery_api/management/commands/post_downloads_summary.py b/api/data_refinery_api/management/commands/post_downloads_summary.py\n--- a/api/data_refinery_api/management/commands/post_downloads_summary.py\n+++ b/api/data_refinery_api/management/commands/post_downloads_summary.py\n@@ -42,28 +42,30 @@\n         unique_users = list(set(annotation.dataset.email_address for annotation in annotations))\n         unique_ips = list(set(annotation.data[\"ip\"] for annotation in annotations))\n \n-        if unique_users:\n-            fallback_text = \"In the last {0} days, {1} users downloaded datasets from {2} locations.\".format(\n-                days, len(unique_users), len(unique_ips)\n-            )\n-        else:\n-            fallback_text = \"There were no downloads in the last {0} days.\".format(days)\n-\n         new_users = \"\"\n         returning_users = \"\"\n+        total_downloads = 0\n         for email in unique_users:\n             user_annotations = annotation_queryset.filter(dataset__email_address=email)\n-            total_downloads = user_annotations.count()\n+            downloads = user_annotations.count()\n+            total_downloads += downloads\n             unique_locations = list(set(annotation.data[\"ip\"] for annotation in user_annotations))\n             locations = \", \".join(get_ip_location(ip) for ip in unique_locations)\n-            is_new_user = DatasetAnnotation.objects.filter(\n+            is_returning_user = DatasetAnnotation.objects.filter(\n                 created_at__lt=start_time, dataset__email_address=email\n             )\n-            text = \"{0} | {1} downloads from {2}\\n\".format(email, total_downloads, locations)\n-            if is_new_user:\n-                new_users += text\n-            else:\n+            text = \"{0} | {1} downloads from {2}\\n\".format(email, downloads, locations)\n+            if is_returning_user:\n                 returning_users += text\n+            else:\n+                new_users += text\n+\n+        if total_downloads > 0:\n+            fallback_text = \"In the last {0} days, {1} users downloaded {2} datasets from {3} locations.\".format(\n+                days, len(unique_users), total_downloads, len(unique_ips)\n+            )\n+        else:\n+            fallback_text = \"There were no downloads in the last {0} days.\".format(days)\n \n         blocks = [\n             {\n", "issue": "Engagement bot thinks every user is a returning user\n### Context\r\n\r\nhttps://alexslemonade.slack.com/archives/CRK42AL1Y/p1587988808265500\r\n\r\n### Problem or idea\r\n\r\n@dvenprasad says 6 of those are new users. There must be a bug in the queries it uses or something.\r\n\r\n### Solution or next step\r\n\r\nFix the engagement bot so it reports new users as new users.\n", "before_files": [{"content": "import datetime\n\nfrom django.conf import settings\nfrom django.core.management.base import BaseCommand\nfrom django.utils import timezone\n\nimport requests\n\nfrom data_refinery_common.models import DatasetAnnotation\n\n\nclass Command(BaseCommand):\n    help = \"Post downloads summary to slack\"\n\n    def add_arguments(self, parser):\n        parser.add_argument(\n            \"--days\",\n            type=int,\n            default=7,  # default to a week\n            help=(\"Number of days in the past for which to build the stats\"),\n        )\n        parser.add_argument(\n            \"--channel\",\n            type=str,\n            default=\"ccdl-general\",\n            help=(\"Optional parameter to choose the channel where the message will be posted.\"),\n        )\n\n    def handle(self, *args, **options):\n        days = options[\"days\"]\n        start_time = timezone.now() - datetime.timedelta(days=days)\n\n        annotation_queryset = DatasetAnnotation.objects.filter(\n            created_at__gt=start_time\n        ).prefetch_related(\"dataset\")\n        annotations = [\n            annotation\n            for annotation in annotation_queryset\n            if annotation.data[\"start\"] and should_display_email(annotation.dataset.email_address)\n        ]\n\n        unique_users = list(set(annotation.dataset.email_address for annotation in annotations))\n        unique_ips = list(set(annotation.data[\"ip\"] for annotation in annotations))\n\n        if unique_users:\n            fallback_text = \"In the last {0} days, {1} users downloaded datasets from {2} locations.\".format(\n                days, len(unique_users), len(unique_ips)\n            )\n        else:\n            fallback_text = \"There were no downloads in the last {0} days.\".format(days)\n\n        new_users = \"\"\n        returning_users = \"\"\n        for email in unique_users:\n            user_annotations = annotation_queryset.filter(dataset__email_address=email)\n            total_downloads = user_annotations.count()\n            unique_locations = list(set(annotation.data[\"ip\"] for annotation in user_annotations))\n            locations = \", \".join(get_ip_location(ip) for ip in unique_locations)\n            is_new_user = DatasetAnnotation.objects.filter(\n                created_at__lt=start_time, dataset__email_address=email\n            )\n            text = \"{0} | {1} downloads from {2}\\n\".format(email, total_downloads, locations)\n            if is_new_user:\n                new_users += text\n            else:\n                returning_users += text\n\n        blocks = [\n            {\n                \"type\": \"section\",\n                \"text\": {\"type\": \"plain_text\", \"emoji\": True, \"text\": fallback_text},\n            }\n        ]\n        if new_users:\n            blocks.append(\n                {\n                    \"type\": \"section\",\n                    \"text\": {\"type\": \"mrkdwn\", \"text\": \"*New users* \\n\" + new_users,},\n                }\n            )\n        if returning_users:\n            blocks.append(\n                {\n                    \"type\": \"section\",\n                    \"text\": {\"type\": \"mrkdwn\", \"text\": \"*Returning users* \\n\" + returning_users,},\n                }\n            )\n\n        # Post to slack\n        requests.post(\n            settings.ENGAGEMENTBOT_WEBHOOK,\n            json={\n                \"username\": \"EngagementBot\",\n                \"icon_emoji\": \":halal:\",\n                \"channel\": \"#\" + options[\"channel\"],\n                \"text\": fallback_text,\n                \"blocks\": blocks,\n            },\n            headers={\"Content-Type\": \"application/json\"},\n            timeout=10,\n        )\n\n\ndef should_display_email(email: str) -> bool:\n    \"\"\" Returns true if the given email is not associated with the CCDL suers \"\"\"\n    if not email:\n        return False\n    return not (\n        email.startswith(\"cansav09\")\n        or email.startswith(\"arielsvn\")\n        or email.startswith(\"jaclyn.n.taroni\")\n        or email.startswith(\"kurt.wheeler\")\n        or email.startswith(\"greenescientist\")\n        or email.startswith(\"miserlou\")\n        or email.startswith(\"d.prasad\")\n        or email.endswith(\"@alexslemonade.org\")\n        or email is (\"daniel.himmelstein@gmail.com\")\n        or email is (\"dv.prasad991@gmail.com\")\n    )\n\n\ndef get_ip_location(remote_ip):\n    try:\n        data = requests.get(\"https://ipapi.co/\" + remote_ip + \"/json/\", timeout=10).json()\n        return \"{0}, {1}\".format(data[\"city\"], data[\"country_name\"])\n    except Exception:\n        return remote_ip\n", "path": "api/data_refinery_api/management/commands/post_downloads_summary.py"}]}