Skip to content

Commit

Permalink
Merge b5c8ef7 into 06214f9
Browse files Browse the repository at this point in the history
  • Loading branch information
babbageLabs committed Dec 21, 2018
2 parents 06214f9 + b5c8ef7 commit 6ccf46b
Show file tree
Hide file tree
Showing 27 changed files with 1,125 additions and 85 deletions.
5 changes: 3 additions & 2 deletions Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
release: ./release-tasks.sh
web: gunicorn authors.wsgi —-log-file -
release: ./release-tasks.sh
web: gunicorn authors.wsgi —-log-file -
worker: python manage.py qcluster
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ No additional parameters required
`GET /api/tags`

### Search & Filter
The application offers an endpoint for filtering and searching for article
The application offers an endpoint for filtering and searching for article
using different criteria as follows.
##### Filter
`GET /api/articles/q/filter/< ?param=value&param2=value >`
Expand Down Expand Up @@ -465,6 +465,9 @@ all the above parameters take the following additional options as
touch .env
echo "DATABASE_URL=postgres://username:password@host/db_name" >> .env
echo "DEBUG=on" >> .env
python manage.py migrate
python manage.py runserver
python manage.py migrate
python manage.py createcachetable
python manage.py qcluster
python manage.py qmonitor
python manage.py runserver
```
44 changes: 44 additions & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import logging
from django.db import models
from rest_framework.reverse import reverse

from authors.apps.authentication.models import User

from django.db.models.signals import post_save
from django.dispatch import receiver

# Create your models here.
from authors.apps.notifier.utils import Notifier
from authors.apps.profiles.models import Profile

logger = logging.getLogger(__name__)


class Articles(models.Model):
Expand All @@ -25,3 +35,37 @@ def __str__(self):

class Meta:
ordering = ["-createdAt", "-updatedAt"]


# signal handlers
@receiver(post_save, sender=Articles)
def articles_notifications_handler(sender, **kwargs):
# create a notification
article = kwargs['instance']
author = article.author
profile = Profile.objects.get_or_create(user=author)
profile = profile[0]

followers = profile.get_followers().values('follower')
qs = User.objects.filter(pk=None)
for user in followers:
u = User.objects.filter(pk=user['follower'])
qs = Notifier.intersect_querysets(qs, u)

url = reverse('articleSpecific', args=[article.slug, ])
reverse_url = reverse('mailing-list-status')
subject = "New Publication Notification"
message = """
%s published a new article.Check it out at %s .
You are seeing this email because you are subscribed to /n
receive email notifications.To unsubscribe from this emails
login and unsubscribe by following %s
""" % (author.email, url, reverse_url)

Notifier.notify_multiple(actor=author,
recipients=qs,
action_object=article,
verb="published a new article",
message=message,
subject=subject
)
7 changes: 3 additions & 4 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ def paginate_queryset(self, queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(
queryset,
self.request,
view=self)
queryset,
self.request,
view=self)

def get_paginated_response(self, data):

Expand All @@ -57,7 +57,6 @@ def get_paginated_response(self, data):
assert self.paginator is not None
return Response({'message': 'cannot return paginated data'})


@staticmethod
def post(request, **kwargs):
"""Create a new article"""
Expand Down
42 changes: 41 additions & 1 deletion authors/apps/authentication/tests/factories/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from factory import fuzzy

from authors.apps.articles.models import Articles
from authors.apps.comments.models import Comment
from authors.apps.favourite.models import Favourite
from authors.apps.notifier.models import MailingList
from authors.apps.profiles.models import Profile, Following


Expand Down Expand Up @@ -32,7 +35,7 @@ class Meta:
model = Profile
django_get_or_create = ('user',)

user = factory.SubFactory(UserFactory)
user = factory.SubFactory(UserFactory2)


class FollowerFactory(factory.DjangoModelFactory):
Expand All @@ -57,3 +60,40 @@ class Meta:
tagList = fuzzy.FuzzyChoice(['music', 'tech', 'lifestyle', 'money'])
slug = slugify(title)
author = factory.SubFactory(UserFactory2)


class FavouritesFactory(factory.DjangoModelFactory):
class Meta:
model = Favourite
django_get_or_create = ('user', 'article',)

user = factory.SubFactory(ProfileFactory)
article = factory.SubFactory(ArticlesFactory)
favourite = factory.Faker(
'random_element',
elements=[x[0] for x in Favourite.FAVOURITE_CHOICES]
)


class CommentFactory(factory.DjangoModelFactory):
class Meta:
model = Comment
django_get_or_create = ('commenter', 'article')

commenter = factory.SubFactory(ProfileFactory)
article = factory.SubFactory(ArticlesFactory)
body = factory.fuzzy.FuzzyText(length=50, prefix="comment")


class MailingListFactory(factory.DjangoModelFactory):
class Meta:
model = MailingList
django_get_or_create = ('user',)

user = factory.SubFactory(UserFactory2)
email_notifications = factory.Faker(
'random_element',
elements=[x for x in [True, False]])
push_notifications = factory.Faker(
'random_element',
elements=[x for x in [True, False]])
46 changes: 46 additions & 0 deletions authors/apps/comments/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import logging

from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.reverse import reverse

from authors.apps.articles.models import Articles
from authors.apps.favourite.models import Favourite
from authors.apps.profiles.models import Profile
from authors.apps.notifier.utils import Notifier

# Create your models here.
logger = logging.getLogger(__file__)


class Comment(models.Model):
Expand All @@ -12,3 +21,40 @@ class Comment(models.Model):
updatedAt = models.DateTimeField(auto_now=True)
commenter = models.ForeignKey(Profile, on_delete=models.CASCADE)
article = models.ForeignKey(Articles, on_delete=models.CASCADE)


@receiver(post_save, sender=Comment)
def comments_notifications_handler(sender, created, **kwargs):
"""notify all people who have favourited an article """
if created:
logger.info("Notification for comment creation")
comment = kwargs['instance']
logger.debug(comment)
favourites = Favourite.objects.filter(article=comment.article)
# notify favouriters if they exist
if len(favourites) > 0:
fav = favourites[0]
recipients = fav.get_favouriters()

url = reverse('articleSpecific', args=[comment.article.slug, ])
reverse_url = reverse('mailing-list-status')
subject = "New Publication Comment Notification"
message = """
%s commented on an article you favourited.Check it out at %s .
You are seeing this email because you are subscribed to /n
receive email notifications.To unsubscribe from this emails
login and unsubscribe by following %s
""" % (comment.commenter.user.email, url, reverse_url)

Notifier.notify_multiple(
actor=comment.commenter,
action_object=comment.article,
verb="Commented on the article",
recipients=recipients,
message=message,
subject=subject
)
else:
logger.debug("No Notifications made for comment %s" % comment)
1 change: 0 additions & 1 deletion authors/apps/comments/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
Expand Down
2 changes: 1 addition & 1 deletion authors/apps/favourite/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


class FavouriteConfig(AppConfig):
name = 'favourite'
name = 'authors.apps.favourite'
58 changes: 58 additions & 0 deletions authors/apps/favourite/models.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
"""
Models for Favourite app
"""
import logging

from django.contrib.auth import get_user_model
from django.db import models

# local imports
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.reverse import reverse

from authors.apps.articles.models import Articles
from authors.apps.authentication.models import User
from authors.apps.notifier.utils import Notifier
from authors.apps.profiles.models import Profile

logger = logging.getLogger(__file__)


# Create your models here.
class Favourite(models.Model):
Expand All @@ -26,3 +37,50 @@ class Favourite(models.Model):

class Meta:
unique_together = ('user', 'article', 'favourite')

def get_favouriters(self):
"""
Reuturn users who have favourited an article
:return:
"""
article = self.article
favourites = Favourite.objects.filter(article=article, favourite=1)
favouriters = favourites.values('user')
# get a null queryset and append users to it
user = get_user_model()
users = user.objects.filter(pk=None)
for favouriter in favouriters:
logger.debug(favouriter)
u = user.objects.filter(pk=favouriter['user'])
users = Notifier.intersect_querysets(users, u)
# return a queryset of users
return users


@receiver(post_save, sender=Favourite)
def fovourites_notifications_handler(sender, created, **kwargs):
"""Notify the author when their article is favourited"""
instance = kwargs['instance']
if created:
logger.debug("article %s has been favourited by %s" % (
instance.article, instance.user))

url = reverse('articleSpecific', args=[instance.article.slug, ])
reverse_url = reverse('mailing-list-status')

subject = "New Article favourite Notification"
Message = """
Your article %s has been favourited by %s.
You are seeing this email because you are subscribed to /n
receive email notifications.To unsubscribe from this emails
login and unsubscribe by following %s
""" % (url, instance.user.username, reverse_url)

Notifier.notify_multiple(
actor=instance.user,
action_object=instance.article,
verb="Commented on the article",
recipients=User.objects.filter(pk=instance.user.pk),
message=Message,
subject=subject
)
Empty file added authors/apps/favourite/tests.py
Empty file.
Empty file.
Empty file added authors/apps/notifier/admin.py
Empty file.
5 changes: 5 additions & 0 deletions authors/apps/notifier/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class NotificationsConfig(AppConfig):
name = 'authors.apps.notifier'
34 changes: 34 additions & 0 deletions authors/apps/notifier/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django.contrib.auth import get_user_model
from django.db import models


# Create your models here.

class MailingList(models.Model):
"""A table containing users who receive email notifier"""
user = models.ForeignKey(get_user_model(),
on_delete=models.CASCADE,
)
# The status of the user with regards to receiving notifier
email_notifications = models.BooleanField(default=True)
push_notifications = models.BooleanField(default=True)

def is_email_subscribed(user):
"""
Verify that a user is subscribed to receive email notifier
:param user:
:return bool:
"""
obj = MailingList.objects.get_or_create(
user=user)
return obj[0].email_notifications

def is_push_subscribed(user):
"""
Verify that a user is subscribed to receive push notifier
:param user:
:return bool:
"""
obj = MailingList.objects.get_or_create(
user=user)
return obj[0].push_notifications
Loading

0 comments on commit 6ccf46b

Please sign in to comment.