Skip to content
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

Add violations backend code #447

Merged
merged 11 commits into from
May 10, 2022
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
1 change: 1 addition & 0 deletions zubhub_backend/compose/web/dev/start
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ python /zubhub_backend/zubhub/manage.py createcachetable

python /zubhub_backend/zubhub/manage.py populate_countries
python /zubhub_backend/zubhub/manage.py populate_categories
python /zubhub_backend/zubhub/manage.py populate_violation_reasons
python /zubhub_backend/zubhub/manage.py populate_initial_creator_tags

exec /usr/local/bin/gunicorn zubhub.wsgi --reload --threads=3 --timeout 155 --bind 0.0.0.0:8000 \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2022-04-30 01:48

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('creators', '0008_auto_20220222_0254'),
]

operations = [
migrations.AlterField(
model_name='setting',
name='contact',
field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'WHATSAPP'), (2, 'EMAIL'), (3, 'SMS'), (4, 'WEB')], default=3, null=True),
),
]
51 changes: 29 additions & 22 deletions zubhub_backend/zubhub/creators/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ def activity_notification(activities, **kwargs):
if len(phone_contexts) > 0 and ctx_values:
send_mass_text.delay(template_name=template_name, ctxs=phone_contexts)


def perform_creator_search(user, query_string):
from creators.models import CreatorTag
"""
Expand All @@ -254,28 +255,28 @@ def perform_creator_search(user, query_string):
rank = SearchRank(F('search_vector'), query)
result_creators = None


# fetch all creators whose creatortag(s) matches the search query
result_tags = CreatorTag.objects.filter(
search_vector=query).prefetch_related("creators")

for tag in result_tags:
result_creators = tag.creators.filter(is_active=True).annotate(rank=rank).order_by('-rank')
result_creators = tag.creators.filter(is_active=True).annotate(
rank=rank).order_by('-rank')
############################################################

# fetch all creators that matches the search term
if result_creators:
result_creators.union(get_user_model().objects.annotate(rank=rank).filter(
search_vector=query, is_active=True ).order_by('-rank'))
result_creators.union(get_user_model().objects.annotate(
rank=rank).filter(search_vector=query,
is_active=True).order_by('-rank'))
else:
result_creators = get_user_model().objects.annotate(rank=rank).filter(
search_vector=query,is_active=True ).order_by('-rank')
search_vector=query, is_active=True).order_by('-rank')
##############################################################

return result_creators



def custom_set_creatortags_queryset(creator, creatortags):
"""
Handle the process of assigning a queryset of creatortags to creator.tags
Expand All @@ -298,22 +299,26 @@ def custom_set_creatortags_queryset(creator, creatortags):

tag = CreatorTag.objects.filter(name="staff").first()
if creatortags.filter(name=tag.name).exists():
creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag))
creator.tags.set(
enforce_creator__creator_tags_constraints(creator, tag))
creatortags = creatortags.exclude(name=tag.name)

tag = CreatorTag.objects.filter(name="moderator").first()
if creatortags.filter(name=tag.name).exists():
creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag))
creator.tags.set(
enforce_creator__creator_tags_constraints(creator, tag))
creatortags = creatortags.exclude(name=tag.name)

tag = CreatorTag.objects.filter(name="group").first()
if creatortags.filter(name=tag.name).exists():
creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag))
creator.tags.set(
enforce_creator__creator_tags_constraints(creator, tag))
creatortags = creatortags.exclude(name=tag.name)

tag = CreatorTag.objects.filter(name="creator").first()
if creatortags.filter(name=tag.name).exists():
creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag))
creator.tags.set(
enforce_creator__creator_tags_constraints(creator, tag))
creatortags = creatortags.exclude(name=tag.name)


Expand All @@ -336,25 +341,29 @@ def enforce_creator__creator_tags_constraints(creator, tag):

if tag.name == "creator":
""" If tag is 'creator', ensure that 'staff', 'moderator' and 'group' tags are not in the user's tags list """
diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group", "moderator"])
diff = CreatorTag.objects.filter(
name__in=["creator", "staff", "group", "moderator"])
tags_to_set = creator.tags.difference(diff)
return tags_to_set.union(diff.filter(name=tag.name))

elif tag.name == "staff":
""" If tag is 'staff', ensure that 'creator' and 'group' tags are not in the user's tags list """
diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group"])
diff = CreatorTag.objects.filter(
name__in=["creator", "staff", "group"])
tags_to_set = creator.tags.difference(diff)
return tags_to_set.union(diff.filter(name=tag.name))

elif tag.name == "moderator":
""" If tag is 'moderator', ensure that 'creator' and 'group' tags are not in the user's tags list """
diff = CreatorTag.objects.filter(name__in=["creator", "group", "moderator"])
diff = CreatorTag.objects.filter(
name__in=["creator", "group", "moderator"])
tags_to_set = creator.tags.difference(diff)
return tags_to_set.union(diff.filter(name=tag.name))

elif tag.name == "group":
""" If tag is 'group', ensure that 'staff', 'creator' and 'moderator' tags are not in the user's tags list """
diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group", "moderator"])
diff = CreatorTag.objects.filter(
name__in=["creator", "staff", "group", "moderator"])
tags_to_set = creator.tags.difference(diff)
return tags_to_set.union(diff.filter(name=tag.name))

Expand All @@ -368,16 +377,14 @@ def enforce_creator__creator_tags_constraints(creator, tag):
return creator.tags.all()



ALL_SETTINGS = {Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB}
enabled_notification_settings: Dict[Notification.Type, Set[int]] = {
Notification.Type.BOOKMARK: {Setting.WEB},
Notification.Type.CLAP: {Setting.WEB},
Notification.Type.COMMENT:
{Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB},
Notification.Type.FOLLOW:
{Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB},
Notification.Type.FOLLOWING_PROJECT:
{Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB},
Notification.Type.COMMENT: ALL_SETTINGS,
Notification.Type.FOLLOW: ALL_SETTINGS,
Notification.Type.FOLLOWING_PROJECT: ALL_SETTINGS,
Notification.Type.PROJECT_VIOLATION: ALL_SETTINGS
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2022-04-30 01:48

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('notifications', '0009_alter_notification_sources'),
]

operations = [
migrations.AlterField(
model_name='notification',
name='type',
field=models.PositiveSmallIntegerField(choices=[(1, 'Bookmark'), (2, 'Clap'), (3, 'Comment'), (4, 'Follow'), (5, 'Following Project'), (6, 'Project Violation')]),
),
]
23 changes: 15 additions & 8 deletions zubhub_backend/zubhub/notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,28 @@


class Notification(models.Model):

class Type(models.IntegerChoices):
BOOKMARK = 1
CLAP = 2
COMMENT = 3
FOLLOW = 4
FOLLOWING_PROJECT = 5
PROJECT_VIOLATION = 6

id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False, unique=True)
type = models.PositiveSmallIntegerField(
choices=Type.choices,
)
recipient = models.ForeignKey(
Creator, on_delete=models.CASCADE, null=True, related_name="notification_recipient", blank=True)
sources = models.ManyToManyField(Creator, related_name='notification_source', blank=True)
id = models.UUIDField(primary_key=True,
default=uuid.uuid4,
editable=False,
unique=True)
type = models.PositiveSmallIntegerField(choices=Type.choices, )
recipient = models.ForeignKey(Creator,
on_delete=models.CASCADE,
null=True,
related_name="notification_recipient",
blank=True)
sources = models.ManyToManyField(Creator,
related_name='notification_source',
blank=True)
message = models.CharField(max_length=255, blank=True, null=True)
link = models.CharField(max_length=1000, blank=True, null=True)
viewed = models.BooleanField(default=False)
Expand Down
64 changes: 43 additions & 21 deletions zubhub_backend/zubhub/projects/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from treebeard.admin import TreeAdmin
from treebeard.forms import movenodeform_factory
from django.conf import settings
from .models import (Project, Comment, Image, StaffPick,
Category, Tag, PublishingRule)
from .models import (Project, Comment, Image, StaffPick, Category, Tag,
PublishingRule, Violation, ViolationReason)
from .utils import project_changed, send_staff_pick_notification
from projects.tasks import delete_file_task
from creators.utils import activity_notification
Expand All @@ -24,20 +24,22 @@ class InlineProjectComments(admin.StackedInline):
class InlineProject(admin.StackedInline):
model = Project.staff_picks.through


class ImageAdmin(admin.ModelAdmin):
search_fields = ["project__title", "image_url"]
list_display = ["image_url"]
exclude = ["id"]
list_per_page = 50 ## paginate when more than 50 items
list_per_page = 50 ## paginate when more than 50 items


class CommentAdmin(TreeAdmin):
list_display = ["creator", "text", "created_on", "publish"]

search_fields = ["project__tite",
"creator__username", "text", "created_on"]

search_fields = [
"project__tite", "creator__username", "text", "created_on"
]
list_filter = ["created_on"]
list_per_page = 50 ## paginate when more than 50 items
list_per_page = 50 ## paginate when more than 50 items

form = movenodeform_factory(Comment)

Expand All @@ -51,18 +53,24 @@ def get_readonly_fields(self, request, obj=None):


class ProjectAdmin(admin.ModelAdmin):
list_display = ["title", "creator", "views_count", "likes_count",
"comments_count", "created_on", "publish"]

search_fields = ["title", 'creator__username', 'creator__email',
"created_on"]
list_display = [
"title", "creator", "views_count", "likes_count", "comments_count",
"created_on", "publish"
]

search_fields = [
"title", 'creator__username', 'creator__email', "created_on"
]
list_filter = ['created_on']
inlines = [InlineProjectImages, InlineProjectComments]
exclude = ["search_vector"]
list_per_page = 50 ## paginate when more than 50 items
list_per_page = 50 ## paginate when more than 50 items

def get_readonly_fields(self, request, obj=None):
return ["id", "slug", "views_count", "likes_count", "comments_count", "created_on"]
return [
"id", "slug", "views_count", "likes_count", "comments_count",
"created_on"
]

def save_model(self, request, obj, form, change):
if change:
Expand All @@ -72,10 +80,12 @@ def save_model(self, request, obj, form, change):

if change:
new = Project.objects.get(pk=obj.pk)
if old.video.find("cloudinary.com") > -1 and old.video != new.video:
if old.video.find(
"cloudinary.com") > -1 and old.video != new.video:
delete_file_task.delay(old.video)
elif old.video.startswith("{0}://{1}".format(settings.DEFAULT_MEDIA_SERVER_PROTOCOL,
settings.DEFAULT_MEDIA_SERVER_DOMAIN)) and old.video != new.video:
elif old.video.startswith("{0}://{1}".format(
settings.DEFAULT_MEDIA_SERVER_PROTOCOL, settings.
DEFAULT_MEDIA_SERVER_DOMAIN)) and old.video != new.video:
delete_file_task.delay(old.video)
if project_changed(old, new):
info = {
Expand All @@ -85,8 +95,6 @@ def save_model(self, request, obj, form, change):
activity_notification(["edited_project"], **info)




def projects_count(obj):
if obj:
return obj.projects.count()
Expand Down Expand Up @@ -136,7 +144,19 @@ class tagAdmin(admin.ModelAdmin):
search_fields = ["name"]
readonly_fields = ["slug"]
exclude = ["id", "search_vector"]
list_per_page = 50 ## paginate when more than 50 items
list_per_page = 50 ## paginate when more than 50 items


class ViolationReasonsAdmin(admin.ModelAdmin):
search_fields = ['description']
exclude = ["id"]
list_per_page = 50


class ViolationAdmin(admin.ModelAdmin):
search_fields = ["name"]
exclude = ["id"]
list_per_page = 50


admin.site.register(Project, ProjectAdmin)
Expand All @@ -145,3 +165,5 @@ class tagAdmin(admin.ModelAdmin):
admin.site.register(Category, categoryAdmin)
admin.site.register(Tag, tagAdmin)
admin.site.register(StaffPick, StaffPickAdmin)
admin.site.register(ViolationReason, ViolationReasonsAdmin)
admin.site.register(Violation, ViolationAdmin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from projects.models import ViolationReason
from django.core.management.base import BaseCommand


class Command(BaseCommand):
help = 'Populate ViolationReason table with violation reasons'

def handle(self, *args, **kwargs):
if ViolationReason.objects.all().count() < 1:
with open(
"./zubhub/projects/management/commands/violation_reasons.txt",
"r") as violation_reasons:
violation_reasons = violation_reasons.readlines()
for violation_reason in violation_reasons:
self.stdout.write(violation_reason)
ViolationReason.objects.create(
description=violation_reason.split("\n")[0])
self.stdout.write(
self.style.SUCCESS(
'The ViolationReason table has been successfully populated!'
))
else:
self.stdout.write(
self.style.NOTICE(
'The ViolationReason table is already populated'))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Promotes bigotry, discrimination, hatred, or violence against any individual or group;
Threatens, harasses, or intimidates any other person, whether that person is a ZubHub user or not;
Contains foul language or personal attacks;
Contains sexually explicit or graphically violent material;
Provides instructions on how to commit illegal activities or obtain illegal products;
Asks any other user for personally identifying information, contact information, or passwords; or
Exposes any others person's personally identifying information, contact information, or passwords without that person's permission.
Loading