From 64d26c022dc182339b33c3cd8e4ef1978b150573 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 20 Aug 2020 11:11:33 +0200 Subject: [PATCH] Move the newsletter. --- src/contact/mailing.py | 74 ------------------- src/newsletter/admin.py | 7 +- src/newsletter/forms.py | 52 +++---------- src/newsletter/migrations/0003_newsletter.py | 31 ++++++++ src/newsletter/models.py | 18 +++-- src/newsletter/subscribe.py | 21 ++++++ .../templates/newsletter/subscribe_email.html | 14 ---- .../templates/newsletter/unsubscribe.html | 6 -- .../newsletter/unsubscribe_email.html | 6 -- .../newsletter/unsubscribe_form.html | 15 ---- .../templates/newsletter/unsubscribed.html | 7 -- src/newsletter/urls.py | 11 +-- src/newsletter/views.py | 47 ++---------- 13 files changed, 93 insertions(+), 216 deletions(-) delete mode 100644 src/contact/mailing.py create mode 100644 src/newsletter/migrations/0003_newsletter.py create mode 100644 src/newsletter/subscribe.py delete mode 100644 src/newsletter/templates/newsletter/subscribe_email.html delete mode 100644 src/newsletter/templates/newsletter/unsubscribe.html delete mode 100644 src/newsletter/templates/newsletter/unsubscribe_email.html delete mode 100644 src/newsletter/templates/newsletter/unsubscribe_form.html delete mode 100644 src/newsletter/templates/newsletter/unsubscribed.html diff --git a/src/contact/mailing.py b/src/contact/mailing.py deleted file mode 100644 index 4dee9c5a7..000000000 --- a/src/contact/mailing.py +++ /dev/null @@ -1,74 +0,0 @@ -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. -# -from hashlib import md5 - -from django.conf import settings -from mailchimp3 import MailChimp -from mailchimp3.mailchimpclient import MailChimpError - - -def subscriber_hash(email): - return md5(email.encode('utf-8')).hexdigest() - - -def remove_from_groups(email, client): - group_ids = [] - categories = client.lists.interest_categories.all(list_id=settings.MAILCHIMP_LIST_ID)['categories'] - for category in categories: - groups = client.lists.interest_categories.interests.all( - list_id=settings.MAILCHIMP_LIST_ID, category_id=category['id'])['interests'] - group_ids += [group['id'] for group in groups] - interests = {group_id: False for group_id in group_ids} - client.lists.members.update( - settings.MAILCHIMP_LIST_ID, subscriber_hash(email), - data={'interests': interests}) - - -def subscribe(email, mailing_lists=None): - client = MailChimp(mc_api=settings.MAILCHIMP_API_KEY, timeout=10.0) - try: - member = client.lists.members.get(settings.MAILCHIMP_LIST_ID, subscriber_hash(email)) - except MailChimpError: - pass - else: - if member['status'] != 'subscribed': - remove_from_groups(email, client) - mailing_lists = mailing_lists or [settings.MAILCHIMP_DEFAULT_GROUP] - interests = { - settings.MAILCHIMP_GROUP_IDS[mailing_list]: True - for mailing_list in mailing_lists - if mailing_list in settings.MAILCHIMP_GROUP_IDS - } - client.lists.members.create_or_update( - settings.MAILCHIMP_LIST_ID, subscriber_hash(email), - data={ - 'email_address': email, - 'status_if_new': 'subscribed', - 'status': 'subscribed', - 'interests': interests, - } - ) - - -def unsubscribe(email, mailing_lists=None): - client = MailChimp(mc_api=settings.MAILCHIMP_API_KEY, timeout=10.0) - try: - member = client.lists.members.get(settings.MAILCHIMP_LIST_ID, subscriber_hash(email)) - except MailChimpError: - return - else: - if member['status'] != 'subscribed': - return - mailing_lists = mailing_lists or settings.MAILCHIMP_GROUP_IDS - interests = { - settings.MAILCHIMP_GROUP_IDS[mailing_list]: False - for mailing_list in mailing_lists - if mailing_list in settings.MAILCHIMP_GROUP_IDS - } - client.lists.members.update( - settings.MAILCHIMP_LIST_ID, subscriber_hash(email), - data={ - 'interests': interests, - } - ) diff --git a/src/newsletter/admin.py b/src/newsletter/admin.py index 48134b173..7af7e0d52 100644 --- a/src/newsletter/admin.py +++ b/src/newsletter/admin.py @@ -5,8 +5,8 @@ from django.urls import path from django.contrib import admin from django.http.response import HttpResponse from django.views.decorators.cache import never_cache - -from newsletter.models import Subscription +from modeltranslation.admin import TranslationAdmin +from newsletter.models import Subscription, Newsletter class SubscriptionAdmin(admin.ModelAdmin): @@ -28,3 +28,6 @@ class SubscriptionAdmin(admin.ModelAdmin): admin.site.register(Subscription, SubscriptionAdmin) + + +admin.site.register(Newsletter, TranslationAdmin) diff --git a/src/newsletter/forms.py b/src/newsletter/forms.py index b75b7c6a9..ba086e352 100644 --- a/src/newsletter/forms.py +++ b/src/newsletter/forms.py @@ -3,16 +3,12 @@ # from django.core.exceptions import ValidationError from django.core.validators import validate_email -from django.forms import Form, BooleanField, MultipleChoiceField +from django.forms import Form, BooleanField from django.forms.fields import EmailField -from django.forms.widgets import CheckboxSelectMultiple -from django.template.loader import render_to_string from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _, ugettext - -from contact import mailing -from newsletter.models import Subscription -from wolnelektury.utils import send_noreply_mail +from django.utils.translation import ugettext_lazy as _ +from newsletter.subscribe import subscribe +from .models import Newsletter class NewsletterForm(Form): @@ -21,7 +17,7 @@ class NewsletterForm(Form): required=False, initial=False, label=_('I want to receive Wolne Lektury\'s newsletter.')) mailing = False mailing_field = 'agree_newsletter' - mailing_list = 'general' + newsletter = None data_processing_part1 = '''\ Administratorem danych osobowych jest Fundacja Nowoczesna Polska (ul. Marszałkowska 84/92 lok. 125, 00-514 Warszawa). @@ -36,6 +32,10 @@ Więcej informacji w polityce prywatności.''' return mark_safe('%s %s %s' % (self.data_processing_part1, self.data_processing_part2, self.data_processing_part3)) def save(self, *args, **kwargs): + newsletter = self.newsletter or Newsletter.objects.filter(slug='').first() + if not newsletter: + return + try: # multiple inheritance mode super(NewsletterForm, self).save(*args, **kwargs) @@ -49,11 +49,7 @@ Więcej informacji w polityce prywatności.''' except ValidationError: pass else: - # subscription, created = Subscription.objects.get_or_create(email=email, defaults={'active': False}) - # send_noreply_mail( - # ugettext('Confirm your subscription to Wolne Lektury newsletter'), - # render_to_string('newsletter/subscribe_email.html', {'subscription': subscription}), [email]) - mailing.subscribe(email, mailing_lists=[self.mailing_list]) + subscribe(email, newsletter=newsletter) class SubscribeForm(NewsletterForm): @@ -62,31 +58,7 @@ class SubscribeForm(NewsletterForm): email = EmailField(label=_('email address')) - def __init__(self, mailing_list, *args, **kwargs): - self.mailing_list = mailing_list + def __init__(self, newsletter, *args, **kwargs): + self.newsletter = newsletter super(SubscribeForm, self).__init__(*args, **kwargs) - -class UnsubscribeForm(Form): - email = EmailField(label=_('email address')) - - def clean(self): - email = self.cleaned_data.get('email') - try: - subscription = Subscription.objects.get(email=email) - except Subscription.DoesNotExist: - raise ValidationError(ugettext('Email address not found.')) - self.cleaned_data['subscription'] = subscription - - def save(self): - subscription = self.cleaned_data['subscription'] - subscription.active = False - subscription.save() - mailing.unsubscribe(subscription.email) - - context = {'subscription': subscription} - # refactor to send_noreply_mail - send_noreply_mail( - ugettext('Unsubscribe from Wolne Lektury\'s newsletter.'), - render_to_string('newsletter/unsubscribe_email.html', context), - [subscription.email], fail_silently=True) diff --git a/src/newsletter/migrations/0003_newsletter.py b/src/newsletter/migrations/0003_newsletter.py new file mode 100644 index 000000000..158d5d2d9 --- /dev/null +++ b/src/newsletter/migrations/0003_newsletter.py @@ -0,0 +1,31 @@ +# Generated by Django 2.2.10 on 2020-08-20 09:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('newsletter', '0002_auto_20160914_1452'), + ] + + operations = [ + migrations.CreateModel( + name='Newsletter', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('slug', models.SlugField(blank=True)), + ('page_title', models.CharField(blank=True, max_length=255)), + ('page_title_de', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_en', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_es', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_fr', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_it', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_lt', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_pl', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_ru', models.CharField(blank=True, max_length=255, null=True)), + ('page_title_uk', models.CharField(blank=True, max_length=255, null=True)), + ('phplist_id', models.IntegerField()), + ], + ), + ] diff --git a/src/newsletter/models.py b/src/newsletter/models.py index 38faf342d..af57d381c 100644 --- a/src/newsletter/models.py +++ b/src/newsletter/models.py @@ -3,16 +3,16 @@ # import hashlib -from django.db.models import Model, EmailField, DateTimeField, BooleanField +from django.db import models from django.utils.translation import ugettext_lazy as _ from django.conf import settings -class Subscription(Model): - email = EmailField(verbose_name=_('email address'), unique=True) - active = BooleanField(default=True, verbose_name=_('active')) - created_at = DateTimeField(auto_now_add=True) - last_modified = DateTimeField(auto_now=True) +class Subscription(models.Model): + email = models.EmailField(verbose_name=_('email address'), unique=True) + active = models.BooleanField(default=True, verbose_name=_('active')) + created_at = models.DateTimeField(auto_now_add=True) + last_modified = models.DateTimeField(auto_now=True) class Meta: verbose_name = _('subscription') @@ -23,3 +23,9 @@ class Subscription(Model): def hashcode(self): return hashlib.sha224(self.email + settings.SECRET_KEY).hexdigest()[:30] + + +class Newsletter(models.Model): + slug = models.SlugField(blank=True) + page_title = models.CharField(max_length=255, blank=True) + phplist_id = models.IntegerField() diff --git a/src/newsletter/subscribe.py b/src/newsletter/subscribe.py new file mode 100644 index 000000000..d7a8a2795 --- /dev/null +++ b/src/newsletter/subscribe.py @@ -0,0 +1,21 @@ +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +import requests + + +def subscribe(email, newsletter): + list_id = newsletter.phplist_id + data = { + "email": email, + "emailconfirm": email, + f"list[{list_id}]": "signup", + "htmlemail": 1, + "subscribe": "Subscribe", + } + response = requests.post( + 'https://mailing.mdrn.pl/?p=subscribe', + data=data, + ) + response.raise_for_status() + diff --git a/src/newsletter/templates/newsletter/subscribe_email.html b/src/newsletter/templates/newsletter/subscribe_email.html deleted file mode 100644 index 2670a48eb..000000000 --- a/src/newsletter/templates/newsletter/subscribe_email.html +++ /dev/null @@ -1,14 +0,0 @@ -Dziękujemy za zapisanie się na newsletter Wolnych Lektur! - -W celu dokończenia rejestracji kliknij w poniższy link: - -https://wolnelektury.pl{% url 'confirm_subscription' subscription_id=subscription.id hashcode=subscription.hashcode %} - -lub skopiuj go do swojej przeglądarki. - -Dopóki tego nie zrobisz, nie będziesz otrzymywał od nas newsletterów. - -Jeżeli jednak otrzymałaś/eś tę wiadomość przez przypadek i nie chcesz otrzymywać newslettera Wolnych Lektur, zignoruj ją. - -Pozdrawiamy, -zespół Wolnych Lektur \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribe.html b/src/newsletter/templates/newsletter/unsubscribe.html deleted file mode 100644 index 06618212e..000000000 --- a/src/newsletter/templates/newsletter/unsubscribe.html +++ /dev/null @@ -1,6 +0,0 @@ -{% extends "base/base.html" %} -{% load i18n %} - -{% block body %} -

{{ page_title }}

-{% endblock %} \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribe_email.html b/src/newsletter/templates/newsletter/unsubscribe_email.html deleted file mode 100644 index fe26a1ab8..000000000 --- a/src/newsletter/templates/newsletter/unsubscribe_email.html +++ /dev/null @@ -1,6 +0,0 @@ -Dziękujemy za dotychczasowe korzystanie z newslettera Wolnych Lektur. -Jeśli w przyszłości zdecydujesz ponownie się na niego zapisać, wypełnij formularz -https://wolnelektury.pl{% url "subscribe" %}, a będziemy Cię na bieżąco informować o naszych działaniach. - -Pozdrawiamy, -zespół Wolnych Lektur \ No newline at end of file diff --git a/src/newsletter/templates/newsletter/unsubscribe_form.html b/src/newsletter/templates/newsletter/unsubscribe_form.html deleted file mode 100644 index d7a6f70af..000000000 --- a/src/newsletter/templates/newsletter/unsubscribe_form.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base/base.html" %} -{% load i18n %} -{% load honeypot %} - -{% block body %} -

{{ page_title }}

-
- {% csrf_token %} - {% render_honeypot_field %} -
    - {{ form.as_ul }} -
  1. -
-
-{% endblock %} diff --git a/src/newsletter/templates/newsletter/unsubscribed.html b/src/newsletter/templates/newsletter/unsubscribed.html deleted file mode 100644 index f96c6134d..000000000 --- a/src/newsletter/templates/newsletter/unsubscribed.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "base/base.html" %} -{% load i18n %} - -{% block body %} -

{{ page_title }}

-

{% trans "You have unsubscribed from Wolne Lektury newsletter. You'll receive a confirmation by email." %}

-{% endblock %} \ No newline at end of file diff --git a/src/newsletter/urls.py b/src/newsletter/urls.py index 290bb87a5..2b0a6f159 100644 --- a/src/newsletter/urls.py +++ b/src/newsletter/urls.py @@ -2,14 +2,15 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from django.urls import path +from django.views.generic import RedirectView from . import views urlpatterns = [ path('zapisz-sie/', views.subscribe_form, name='subscribe'), - path('zapisz-sie/konkurs/', views.subscribe_form, {"title": "Zapisz się na newsletter Konkursu", "mailing_list": "contest"}, name='subscribe-contest'), + path('zapisz-sie//', views.subscribe_form, name='subscribe'), path('zapis/', views.subscribed, name='subscribed'), - path('potwierdzenie///', - views.confirm_subscription, name='confirm_subscription'), - path('wypisz-sie/', views.unsubscribe_form, name='unsubscribe'), - path('wypisano/', views.unsubscribed, name='unsubscribed'), + path('wypisz-sie/', RedirectView.as_view( + url='https://mailing.mdrn.pl/?p=unsubscribe', + permanent=False, + ), name='unsubscribe'), ] diff --git a/src/newsletter/views.py b/src/newsletter/views.py index 6c90873bb..3440a47b7 100644 --- a/src/newsletter/views.py +++ b/src/newsletter/views.py @@ -1,26 +1,25 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # -from django.http import Http404 from django.http.response import HttpResponseRedirect from django.shortcuts import render, get_object_or_404 from django.urls import reverse from django.utils.translation import ugettext_lazy as _ -from newsletter.forms import UnsubscribeForm, SubscribeForm -from newsletter.models import Subscription +from newsletter.forms import SubscribeForm, Newsletter -def subscribe_form(request, mailing_list='general', title=None): +def subscribe_form(request, slug=''): + newsletter = get_object_or_404(Newsletter, slug=slug) if request.POST: - form = SubscribeForm(mailing_list, request.POST) + form = SubscribeForm(newsletter, request.POST) if form.is_valid(): form.save() return HttpResponseRedirect(reverse('subscribed')) else: - form = SubscribeForm(mailing_list) + form = SubscribeForm(newsletter) return render(request, 'newsletter/subscribe_form.html', { - 'page_title': title or _('Subscribe To Newsletter'), + 'page_title': newsletter.page_title, 'form': form, }) @@ -30,37 +29,3 @@ def subscribed(request): 'page_title': _('Subscribed'), }) - -def check_subscription(subscription, hashcode): - if hashcode != subscription.hashcode(): - raise Http404 - - -def confirm_subscription(request, subscription_id, hashcode): - subscription = get_object_or_404(Subscription, id=subscription_id) - check_subscription(subscription, hashcode) - subscription.active = True - subscription.save() - return render(request, 'newsletter/confirm_subscription.html', { - 'page_title': _('Subscription confirmed') - }) - - -def unsubscribe_form(request): - if request.POST: - form = UnsubscribeForm(request.POST) - if form.is_valid(): - form.save() - return HttpResponseRedirect(reverse('unsubscribed')) - else: - form = UnsubscribeForm() - return render(request, 'newsletter/unsubscribe_form.html', { - 'page_title': _('Unsubscribe'), - 'form': form, - }) - - -def unsubscribed(request): - return render(request, 'newsletter/unsubscribed.html', { - 'page_title': _('Unsubscribed'), - }) -- 2.20.1