internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: mozmeao/snippets-service

Issue:
Implement publish start and publish end for SnippetsNG



Discussion:

Resolving patch:
diff --git a/snippets/base/models.py b/snippets/base/models.py
--- a/snippets/base/models.py
+++ b/snippets/base/models.py
@@ -514,6 +514,11 @@ def render_to_as_router(self):
             'content': data,
         }
 
+        if self.publish_start:
+            rendered_snippet['publish_start'] = util.to_unix_time_seconds(self.publish_start)
+        if self.publish_end:
+            rendered_snippet['publish_end'] = util.to_unix_time_seconds(self.publish_end)
+
         return rendered_snippet
 
     @property
diff --git a/snippets/base/util.py b/snippets/base/util.py
--- a/snippets/base/util.py
+++ b/snippets/base/util.py
@@ -1,8 +1,11 @@
+import datetime
 import re
 
 from product_details import product_details
 from product_details.version_compare import version_list
 
+EPOCH = datetime.datetime.utcfromtimestamp(0)
+
 
 def get_object_or_none(model_class, **filters):
     """
@@ -89,3 +92,7 @@ def __call__(self, matchobj):
     replacer = Replacer()
     final_text = re.sub('(<a(?P<attrs> .*?)>)(?P<innerText>.+?)(</a>)', replacer, text)
     return final_text, replacer.links
+
+
+def to_unix_time_seconds(dt):
+    return int((dt - EPOCH).total_seconds())


Test patch:
diff --git a/snippets/base/tests/test_models.py b/snippets/base/tests/test_models.py
--- a/snippets/base/tests/test_models.py
+++ b/snippets/base/tests/test_models.py
@@ -1,7 +1,9 @@
 import json
+from datetime import datetime
 
 from django.conf import settings
 from django.test.utils import override_settings
+
 import brotli
 from jinja2 import Markup
 from mock import ANY, MagicMock, Mock, patch
@@ -303,6 +305,20 @@ def test_render_to_as_router(self):
         }
         self.assertEqual(generated_result, expected_result)
 
+        # Check start date include
+        snippet.publish_start = datetime(2018, 04, 11, 0, 0)
+        snippet.publish_end = None
+        generated_result = snippet.render_to_as_router()
+        self.assertEqual(generated_result['publish_start'], 1523404800)
+        self.assertTrue('publish_end' not in generated_result)
+
+        # Check end date include
+        snippet.publish_start = None
+        snippet.publish_end = datetime(2018, 03, 23, 0, 0)
+        generated_result = snippet.render_to_as_router()
+        self.assertEqual(generated_result['publish_end'], 1521763200)
+        self.assertTrue('publish_start' not in generated_result)
+
 
 class UploadedFileTests(TestCase):
Repository: mozmeao/snippets-service

Issue:
Snippets not displaying as expected for all after the A/S Router implimentation
The five (5) hard-coded AS Router snippets in the Snippets NG base are not displaying as expected for me, but they are for @glogiotatidis. Clearing my browser cache didn't fix this issue.

**Fx GA 61.0.1**
Clicking "Preview URL" in the snippet admin or on the magnifying glass icon in Snippets NG base displays snippets that look like this:
![snippetng-release channel- snippet view](https://user-images.githubusercontent.com/39389621/43339510-5b843a18-918e-11e8-86fd-c01e75d6a69d.png)

**Fx Beta 62.0b12**
Clicking "Preview URL" in the snippet admin or on the magnifying glass icon in Snippets NG base displays snippets that look like this:
![snippet ng-beta channel-snippet view](https://user-images.githubusercontent.com/39389621/43339706-f741c25e-918e-11e8-84f2-98f367e2f9b5.png)

**Clicking the "Preview snippet" button in the snippet admin displays correctly.**


Discussion:
Thanks for reporting @mediaChick 

@ldwright do you have the same issue?

Resolving patch:
diff --git a/snippets/base/views.py b/snippets/base/views.py
--- a/snippets/base/views.py
+++ b/snippets/base/views.py
@@ -191,7 +191,7 @@ def show_snippet(request, snippet_id, uuid=False):
             raise Http404()
 
     template = 'base/preview.jinja'
-    if snippet.on_startpage_5:
+    if snippet.on_startpage_5 or snippet.on_startpage_6:
         template = 'base/preview_as.jinja'
     return render(request, template, {
         'snippets_json': json.dumps([snippet.to_dict()]),


Test patch:
Repository: mozmeao/snippets-service

Issue:
Customize via env vars Django Admin Title and Header.
Set env variables for:
 - [x] dev
 - [x] stage
 - [x] admin (prod)


Discussion:

Resolving patch:
diff --git a/snippets/settings.py b/snippets/settings.py
--- a/snippets/settings.py
+++ b/snippets/settings.py
@@ -232,6 +232,8 @@ def mysql_version(self):
 METRICS_SAMPLE_RATE = config('METRICS_SAMPLE_RATE', default=0.1, cast=float)
 
 SITE_URL = config('SITE_URL', default='')
+SITE_HEADER = config('SITE_HEADER', default='Snippets Administration')
+SITE_TITLE = config('SITE_TITLE', default='Mozilla Snippets')
 
 CACHES = {
     'default': config('CACHE_URL', default='locmem://', cast=django_cache_url.parse),
diff --git a/snippets/urls.py b/snippets/urls.py
--- a/snippets/urls.py
+++ b/snippets/urls.py
@@ -26,8 +26,8 @@ def robots_txt(request):
         url(r'advanced_filters/', include('advanced_filters.urls')),
 
     ]
-    admin.site.site_header = 'Snippets Administration'
-    admin.site.site_title = 'Mozilla Snippets'
+    admin.site.site_header = settings.SITE_HEADER
+    admin.site.site_title = settings.SITE_TITLE
 
 elif settings.ADMIN_REDIRECT_URL:
     urlpatterns.append(


Test patch:
Repository: mozmeao/snippets-service

Issue:
Re-word Firefox Account targeting parameter
We recently learned that the pref for "show only to users with an enabled Firefox Account" actually looks at whether or not someone has Sync enabled (which therefore _tells us_ that someone has a Firefox Account) - now that we know this, it'd be nice to rephrase that targeting parameter to be more accurate in the admin tool.

Proposal to change field values to:
"Show only to FxA users with Sync enabled"
"Show only to users without Sync enabled"

And to clarify: @glogiotatidis Can you confirm that if we choose "Show only to users without Sync enabled" in this case, that we would theoretically be targeting people without a Fx Account _as well as_ people with a Fx Account but do not have Sync enabled? There's no way to tease those two buckets apart at this point, right?

Thanks!
CC for FYI: @mediaChick


Discussion:
> And to clarify: @glogiotatidis Can you confirm that if we choose "Show only to users without Sync enabled" in this case, that we would theoretically be targeting people without a Fx Account as well as people with a Fx Account but do not have Sync enabled? There's no way to tease those two buckets apart at this point, right?

That's correct.

Resolving patch:
diff --git a/snippets/base/forms.py b/snippets/base/forms.py
--- a/snippets/base/forms.py
+++ b/snippets/base/forms.py
@@ -271,10 +271,10 @@ class SnippetAdminForm(BaseSnippetAdminForm):
         choices=[('any', 'No limit'),
                  ('older_than_current_release', 'Older than current release')])
     client_option_has_fxaccount = forms.ChoiceField(
-        label='Firefox Account',
+        label='Firefox Account / Sync',
         choices=(('any', 'Show to all users'),
-                 ('yes', 'Show only to users with an enabled Firefox Account'),
-                 ('no', 'Show only to users without an enabled Firefox Account')))
+                 ('yes', 'Show only to FxA users with Sync enabled'),
+                 ('no', 'Show only to users without Sync enabled')))
     client_option_is_developer = forms.ChoiceField(
         label='Is Developer',
         choices=(('any', 'Show to all users'),


Test patch:
Repository: mozmeao/snippets-service

Issue:
Rename Aurora to Dev edition in UI



Discussion:

Resolving patch:
diff --git a/snippets/base/models.py b/snippets/base/models.py
--- a/snippets/base/models.py
+++ b/snippets/base/models.py
@@ -385,7 +385,7 @@ class Snippet(SnippetBaseModel):
 
     on_release = models.BooleanField(default=False, verbose_name='Release')
     on_beta = models.BooleanField(default=False, verbose_name='Beta')
-    on_aurora = models.BooleanField(default=False, verbose_name='Aurora')
+    on_aurora = models.BooleanField(default=False, verbose_name='Dev Edition (old Aurora)')
     on_nightly = models.BooleanField(default=False, verbose_name='Nightly')
     on_esr = models.BooleanField(default=False, verbose_name='ESR')
 


Test patch:
Repository: mozmeao/snippets-service

Issue:
Update ASRBundle to use STATUS_CHOICES
And in other places. Search for `400` 


Discussion:

Resolving patch:
diff --git a/snippets/base/admin/adminmodels.py b/snippets/base/admin/adminmodels.py
--- a/snippets/base/admin/adminmodels.py
+++ b/snippets/base/admin/adminmodels.py
@@ -48,7 +48,7 @@ class SnippetTemplateVariableInline(admin.TabularInline):
 class SnippetTemplateAdmin(VersionAdmin, admin.ModelAdmin):
     save_on_top = True
     list_display = ('name', 'priority', 'hidden')
-    list_filter = ('hidden',)
+    list_filter = ('hidden', 'startpage')
     inlines = (SnippetTemplateVariableInline,)
     formfield_overrides = {
         TextField: {'widget': AceWidget(mode='html', theme='github',
diff --git a/snippets/base/bundles.py b/snippets/base/bundles.py
--- a/snippets/base/bundles.py
+++ b/snippets/base/bundles.py
@@ -13,7 +13,7 @@
 import brotli
 
 from snippets.base import util
-from snippets.base.models import ASRSnippet, Snippet
+from snippets.base.models import STATUS_CHOICES, ASRSnippet, Snippet
 
 
 ONE_DAY = 60 * 60 * 24
@@ -194,7 +194,7 @@ def filename(self):
     @cached_property
     def snippets(self):
         return (ASRSnippet.objects
-                .filter(status=400)
+                .filter(status=STATUS_CHOICES['Published'])
                 .match_client(self.client)
                 .filter_by_available())
 


Test patch:
diff --git a/snippets/base/tests/__init__.py b/snippets/base/tests/__init__.py
--- a/snippets/base/tests/__init__.py
+++ b/snippets/base/tests/__init__.py
@@ -143,7 +143,7 @@ class ASRSnippetFactory(factory.django.DjangoModelFactory):
     campaign = factory.SubFactory(CampaignFactory, creator=factory.SelfAttribute('..creator'))
 
     template = factory.SubFactory(SnippetTemplateFactory)
-    status = 400  # Published
+    status = models.STATUS_CHOICES['Published']
 
     target = factory.SubFactory(TargetFactory, creator=factory.SelfAttribute('..creator'))
Repository: mozmeao/snippets-service

Issue:
Remove Template Widget Preview button for ASR Snippets



Discussion:

Resolving patch:
diff --git a/snippets/base/forms.py b/snippets/base/forms.py
--- a/snippets/base/forms.py
+++ b/snippets/base/forms.py
@@ -105,14 +105,15 @@ class TemplateDataWidget(forms.TextInput):
     the template variables available for the currently selected template. These
     fields are combined into a JSON string when the form is submitted.
     """
-    def __init__(self, select_name, *args, **kwargs):
+    def __init__(self, select_name, include_preview_button=True, *args, **kwargs):
         self.template_select_name = select_name
+        self.include_preview_button = include_preview_button
         return super(TemplateDataWidget, self).__init__(*args, **kwargs)
 
     def render(self, name, value, attrs=None, renderer=None):
         widget_code = super(TemplateDataWidget, self).render(
             name, value, attrs)
-        return mark_safe(''.join([widget_code, """
+        extra_code = """
             <div class="widget-container">
               <div class="template-data-widget"
                    data-select-name="{select_name}"
@@ -120,15 +121,21 @@ def render(self, name, value, attrs=None, renderer=None):
                    data-snippet-size-limit="{size_limit}"
                    data-snippet-img-size-limit="{img_size_limit}">
               </div>
+        """
+        if self.include_preview_button:
+            extra_code += """
               <div class="snippet-preview-container"
                    data-preview-url="{preview_url}">
               </div>
-            </div>
-        """.format(select_name=self.template_select_name,
-                   input_name=name,
-                   preview_url=reverse('base.preview'),
-                   size_limit=settings.SNIPPET_SIZE_LIMIT,
-                   img_size_limit=settings.SNIPPET_IMAGE_SIZE_LIMIT)
+            """
+        extra_code += '</div>'
+        return mark_safe(''.join([
+            widget_code, extra_code.format(
+                select_name=self.template_select_name,
+                input_name=name,
+                preview_url=reverse('base.preview'),
+                size_limit=settings.SNIPPET_SIZE_LIMIT,
+                img_size_limit=settings.SNIPPET_IMAGE_SIZE_LIMIT)
         ]))
 
     class Media:
@@ -545,7 +552,7 @@ class Meta:
         model = ASRSnippet
         exclude = ['creator', 'created', 'modified']
         widgets = {
-            'data': TemplateDataWidget('template'),
+            'data': TemplateDataWidget('template', include_preview_button=False),
         }
 
 


Test patch:
Repository: mozmeao/snippets-service

Issue:
[new filter] Filter based on y/n auto-download updates enabled
Associated with [Bug 1483057](https://bugzilla.mozilla.org/show_bug.cgi?id=1483057).

Background on request: We'd like to be able to target snippet users based on whether or not they have updates enabled to auto-download or not. Similar to #696 this may be able to help us ascertain a user's level of tech savviness and usage habits, and could possibly be measured against retention.


Discussion:
This lives under `browserSettings.update.autoDownload`

Resolving patch:
diff --git a/snippets/base/admin/adminmodels.py b/snippets/base/admin/adminmodels.py
--- a/snippets/base/admin/adminmodels.py
+++ b/snippets/base/admin/adminmodels.py
@@ -197,6 +197,8 @@ class TargetAdmin(admin.ModelAdmin):
         ('Targeting', {
             'fields': (
                 'filtr_is_default_browser',
+                'filtr_updates_enabled',
+                'filtr_updates_autodownload_enabled',
                 'filtr_profile_age_created',
                 'filtr_uses_firefox_sync',
                 'filtr_is_developer',
diff --git a/snippets/base/forms.py b/snippets/base/forms.py
--- a/snippets/base/forms.py
+++ b/snippets/base/forms.py
@@ -633,6 +633,24 @@ class TargetAdminForm(forms.ModelForm):
         label='Is developer',
         help_text='User has opened Developer Tools more than 5 times.',
         required=False)
+    filtr_updates_enabled = fields.JEXLChoiceField(
+        'browserSettings.update.enabled',
+        choices=((None, "I don't care"),
+                 ('true', 'Yes',),
+                 ('false', 'No')),
+        required=False,
+        label='Has updates enabled',
+        label_suffix='?',
+    )
+    filtr_updates_autodownload_enabled = fields.JEXLChoiceField(
+        'browserSettings.update.autoDownload',
+        choices=((None, "I don't care"),
+                 ('true', 'Yes',),
+                 ('false', 'No')),
+        required=False,
+        label='Is auto-downloading updates',
+        label_suffix='?',
+    )
 
     class Meta:
         model = Target


Test patch:
Repository: mozmeao/snippets-service

Issue:
JEXL targeting: Previous Session Closed
Waiting on ASR implementation https://bugzilla.mozilla.org/show_bug.cgi?id=1484206    


Discussion:
ASR implementation complete.
Re-adding blocked since this has not been uplifted yet

Resolving patch:
diff --git a/snippets/base/admin/adminmodels.py b/snippets/base/admin/adminmodels.py
--- a/snippets/base/admin/adminmodels.py
+++ b/snippets/base/admin/adminmodels.py
@@ -205,6 +205,7 @@ class TargetAdmin(admin.ModelAdmin):
                 'filtr_updates_autodownload_enabled',
                 'filtr_profile_age_created',
                 'filtr_firefox_version',
+                'filtr_previous_session_end',
                 'filtr_uses_firefox_sync',
                 'filtr_is_developer',
                 'filtr_current_search_engine',
diff --git a/snippets/base/forms.py b/snippets/base/forms.py
--- a/snippets/base/forms.py
+++ b/snippets/base/forms.py
@@ -641,6 +641,19 @@ class TargetAdminForm(forms.ModelForm):
         label='Firefox Version',
         help_text='The version of the browser must fall between those two limits.'
     )
+    filtr_previous_session_end = fields.JEXLRangeField(
+        'previousSessionEnd',
+        # previousSessionEnd is in milliseconds. We first calculate the
+        # difference from currentDate and then we convert to week.
+        jexl={
+            'minimum': '((currentDate - previousSessionEnd) / 604800000) >= {value}',
+            'maximum': '((currentDate - previousSessionEnd) / 604800000) < {value}',
+        },
+        choices=PROFILE_AGE_CHOICES_AS,
+        required=False,
+        label='Previous Session End',
+        help_text='How many weeks since the last time Firefox was used?'
+    )
     filtr_uses_firefox_sync = fields.JEXLChoiceField(
         'usesFirefoxSync',
         choices=((None, "I don't care"),
diff --git a/snippets/base/models.py b/snippets/base/models.py
--- a/snippets/base/models.py
+++ b/snippets/base/models.py
@@ -558,6 +558,7 @@ class Target(models.Model):
             'filtr_current_search_engine': str,
             'filtr_browser_addon': str,
             'filtr_total_bookmarks_count': str,
+            'filtr_previous_session_end': str,
         }
     )
     jexl_expr = models.TextField(blank=True, default='')


Test patch:
Repository: mozmeao/snippets-service

Issue:
Add help text with deep links and `[[snippet_id]]` in ASRSnippet
![image](https://user-images.githubusercontent.com/584352/46720224-9c95b980-cc78-11e8-9abf-14352a1657e2.png)



Discussion:

Resolving patch:
diff --git a/snippets/base/admin/adminmodels.py b/snippets/base/admin/adminmodels.py
--- a/snippets/base/admin/adminmodels.py
+++ b/snippets/base/admin/adminmodels.py
@@ -149,6 +149,21 @@ class ASRSnippetAdmin(admin.ModelAdmin):
     fieldsets = (
         ('ID', {'fields': ('creator', 'name', 'status', 'preview_url')}),
         ('Content', {
+            'description': (
+                '''
+                <strong>Available deep links:</strong><br/>
+                <ol>
+                  <li><code>special:accounts</code> to open Firefox Accounts</li>
+                  <li><code>special:appMenu</code> to open the hamburger menu</li>
+                </ol><br/>
+                <strong>Automatically add Snippet ID:</strong><br/>
+                You can use <code>[[snippet_id]]</code> in any field and it
+                will be automatically replaced by Snippet ID when served to users.
+                <br/>
+                Example: This is a <code>&lt;a href=&quot;https://example.com?utm_term=[[snippet_id]]&quot;&gt;link&lt;/a&gt;</code>  # noqa
+                <br/>
+                '''
+            ),
             'fields': ('template', 'data'),
         }),
         ('Publishing Options', {
@@ -160,6 +175,11 @@ class ASRSnippetAdmin(admin.ModelAdmin):
         }),
     )
 
+    class Media:
+        css = {
+            'all': ('css/admin/ASRSnippetAdmin.css',)
+        }
+
     def save_model(self, request, obj, form, change):
         obj.creator = request.user
         statsd.incr('save.asrsnippet')


Test patch:
Repository: mozmeao/snippets-service

Issue:
Create a button to copy to clipboard the preview link on click
Preview link for ASR Snippets cannot be directly clicked and instead must be copied and pasted to the URL bar. Create a `Copy` button next to the link to make the procedure easier. 


Discussion:
Is it possible for that copy button to open that copied url in new:tab?
> Is it possible for that copy button to open that copied url in new:tab?

Unfortunately you'll have to copy and paste as I mentioned in the meeting. This issue is so that copying is easier.

Resolving patch:
diff --git a/snippets/base/admin/adminmodels.py b/snippets/base/admin/adminmodels.py
--- a/snippets/base/admin/adminmodels.py
+++ b/snippets/base/admin/adminmodels.py
@@ -180,6 +180,10 @@ class Media:
         css = {
             'all': ('css/admin/ASRSnippetAdmin.css',)
         }
+        js = (
+            'js/admin/clipboard.min.js',
+            'js/admin/copy_preview.js',
+        )
 
     def save_model(self, request, obj, form, change):
         obj.creator = request.user
@@ -187,7 +191,15 @@ def save_model(self, request, obj, form, change):
         super().save_model(request, obj, form, change)
 
     def preview_url(self, obj):
-        return obj.get_preview_url()
+        text = f'''
+        <span id="previewLinkUrl">{obj.get_preview_url()}</span>
+        <button id="copyPreviewLink" class="btn"
+                data-clipboard-target="#previewLinkUrl"
+                originalText="Copy to Clipboard" type="button">
+          Copy to Clipboard
+        </button>
+        '''
+        return mark_safe(text)
 
 
 class CampaignAdmin(admin.ModelAdmin):


Test patch:
Repository: mozmeao/snippets-service

Issue:
TypeError: Key 'filtr_profile_age_created' should be of type int
https://sentry.prod.mozaws.net/operations/snippets/issues/4875932/


Discussion:

Resolving patch:
diff --git a/snippets/base/models.py b/snippets/base/models.py
--- a/snippets/base/models.py
+++ b/snippets/base/models.py
@@ -551,14 +551,17 @@ class Target(models.Model):
         default={},
         spec={
             'filtr_is_default_browser': str,
-            'filtr_profile_age_created': int,
+            'filtr_profile_age_created': str,
             'filtr_firefox_version': str,
+            'filtr_previous_session_end': str,
             'filtr_uses_firefox_sync': str,
+            'filtr_country': str,
             'filtr_is_developer': str,
+            'filtr_updates_enabled': str,
+            'filtr_updates_autodownload_enabled': str,
             'filtr_current_search_engine': str,
             'filtr_browser_addon': str,
             'filtr_total_bookmarks_count': str,
-            'filtr_previous_session_end': str,
         }
     )
     jexl_expr = models.TextField(blank=True, default='')


Test patch:
Repository: mozmeao/snippets-service

Issue:
UnicodeEncodeError when Slack request.post
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 258-264: Body ('γιώργος') is not valid Latin-1. Use body.encode('utf-8') if you want to send it encoded in UTF-8.

Sentry Issue: https://sentry.prod.mozaws.net/operations/snippets/issues/4891896/


Discussion:

Resolving patch:
diff --git a/snippets/base/slack.py b/snippets/base/slack.py
--- a/snippets/base/slack.py
+++ b/snippets/base/slack.py
@@ -21,7 +21,7 @@ def _send_slack(data):
         return
 
     try:
-        response = requests.post(settings.SLACK_WEBHOOK, data=data,
+        response = requests.post(settings.SLACK_WEBHOOK, data=data.encode('utf-8'),
                                  headers={'Content-Type': 'application/json'},
                                  timeout=4)
         response.raise_for_status()


Test patch:
diff --git a/snippets/base/tests/test_slack.py b/snippets/base/tests/test_slack.py
--- a/snippets/base/tests/test_slack.py
+++ b/snippets/base/tests/test_slack.py
@@ -19,5 +19,5 @@ def test_slack_enabled(self):
             slack._send_slack('foo')
         self.assertTrue(requests_mock.post.called)
         requests_mock.post.assert_called_with(
-            'https://example.com', data='foo', timeout=4,
+            'https://example.com', data=b'foo', timeout=4,
             headers={'Content-Type': 'application/json'})