Skip to content

Commit

Permalink
fix Invites & Referrals
Browse files Browse the repository at this point in the history
  • Loading branch information
JisanAR03 committed Feb 22, 2024
1 parent 832f96f commit e382705
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 44 deletions.
1 change: 1 addition & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
handler500 = "website.views.handler500"

urlpatterns = [
path('referral/', website.views.referral_signup, name='referral_signup'),
path("captcha/", include("captcha.urls")),
re_path(r"^auth/registration/", include("dj_rest_auth.registration.urls")),
path('rest-auth/password/reset/confirm/<str:uidb64>/<str:token>', PasswordResetConfirmView.as_view(),
Expand Down
24 changes: 24 additions & 0 deletions website/migrations/0083_invitefriend_referral_code_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.0.2 on 2024-02-22 21:11

import uuid
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("website", "0082_issue_reporter_ip_address"),
]

operations = [
migrations.AddField(
model_name="invitefriend",
name="referral_code",
field=models.CharField(default=uuid.uuid4, editable=False, max_length=100),
),
migrations.AddField(
model_name="invitefriend",
name="signup_completed",
field=models.BooleanField(default=False),
),
]
5 changes: 5 additions & 0 deletions website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,12 +381,17 @@ class InviteFriend(models.Model):
sender = models.ForeignKey(User, on_delete=models.CASCADE)
recipient = models.EmailField()
sent = models.DateTimeField(auto_now_add=True, db_index=True)
referral_code = models.CharField(max_length=100, default=uuid.uuid4, editable=False)
signup_completed = models.BooleanField(default=False)

class Meta:
ordering = ("-sent",)
verbose_name = "invitation"
verbose_name_plural = "invitations"

def __str__(self):
return f"Invite from {self.sender} to {self.recipient}"


def user_images_path(instance, filename):
from django.template.defaultfilters import slugify
Expand Down
60 changes: 60 additions & 0 deletions website/templates/email/invitation_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
color: #000;
background-color: #fff;
}
.container {
padding: 20px;
}
.header {
color: #fff;
padding: 5px;
text-align: center;
}
.content {
margin-top: 20px;
}
.button {
display: inline-block;
padding: 10px 20px;
margin-top: 20px;
background-color: #e02424;
color: #fff;
text-decoration: none;
font-weight: bold;
}
.footer {
margin-top: 30px;
text-align: center;
padding: 10px;
font-size: 0.8em;
background-color: #f2f2f2;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<img src="https://blt.owasp.org/favicon.ico" alt="BLT Logo">
<h1>Welcome to {{ site_name }}</h1>
</div>
<div class="content">
<p>Hi there!</p>
<p>You've been invited by <strong>{{ sender_username }}</strong> to join our community at <strong>{{ site_name }}</strong>.</p>
<p>We're excited to have you onboard and explore the vast opportunities to find and submit bugs, earn rewards, and be part of our thriving community.</p>
<a href="{{ referral_link }}" class="button">Join Now</a>
</div>
<div class="footer">
<p>&copy; {{ site_name }}. All rights reserved.</p>
</div>
</div>
</body>
</html>
39 changes: 21 additions & 18 deletions website/templates/invite_friend.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
{% extends "base.html" %}
{% block content %}
<form action="{% url 'invite_friend' %}" method="post" class="form-inline">
<form action="{% url 'invite_friend' %}" method="post" class="mx-auto max-w-lg mt-5">
{% csrf_token %}
<div class="row">
{% for error in form.non_field_errors %}
<div class="col-lg-6">{{ error }}</div>
{% endfor %}
</div>
<div class="row">
<div class="col-lg-10">
{% if form.recipient.errors %}
<div class="alert alert-danger">{{ form.recipient.errors }}</div>
{% endif %}
{% for error in form.non_field_errors %}
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<strong class="font-bold">Oops!</strong>
<span class="block sm:inline">{{ error }}</span>
</div>
{% endfor %}

<div class="mb-4">
<label for="recipient" class="block text-gray-700 text-2xl font-bold mb-2">Friends mail:</label>
{{ form.recipient }}
{% if form.recipient.errors %}
<p class="text-red-500 text-xs italic">{{ form.recipient.errors }}</p>
{% endif %}
</div>
<div class="row">
<div class="col-lg-10">
<h3 class="page-header">Invite 2 friends and get 1 point!</h3>
<label>Email:</label>
{{ form.recipient }}
<button type="submit" class="btn btn-danger text-black">Invite</button>
</div>

<div class="flex items-center justify-between">
<button type="submit" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Invite
</button>
<p class="inline-block align-baseline font-bold text-base text-red-500 hover:text-red-800">
Invite a friend to join the site and earn 2 points!
</p>
</div>
</form>
{% endblock %}
110 changes: 84 additions & 26 deletions website/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
from django.core.exceptions import ValidationError
from django.http import HttpRequest
from django.utils.timezone import now
from django.contrib.sites.shortcuts import get_current_site
from allauth.account.signals import user_signed_up
from django.utils.html import strip_tags
from django.core.mail import EmailMultiAlternatives

def is_valid_https_url(url):
validate = URLValidator(schemes=['https']) # Only allow HTTPS URLs
Expand Down Expand Up @@ -2066,38 +2070,57 @@ class CreateInviteFriend(CreateView):
success_url = reverse_lazy("invite_friend")

def form_valid(self, form):
from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site

recipient_email = form.cleaned_data["recipient"]

# Check if a user with the given email already exists
if User.objects.filter(email=recipient_email).exists():
messages.error(self.request, "User with this email already exists.")
return super().form_invalid(form)
# try:
# invite = InviteFriend.objects.get(recipient=recipient_email)
# time_difference = now() - invite.sent
# if time_difference.days < 1: # 1 day
# messages.error(self.request, "An invitation has already been sent to this email recently.")
# return super().form_invalid(form)
# except InviteFriend.DoesNotExist:
# pass
instance = form.save(commit=False)
instance.sender = self.request.user
instance.save()

site = get_current_site(self.request)
referral_link = f"https://{site.domain}/referral/?ref={instance.referral_code}"

mail_status = send_mail(
"Inivtation to {site} from {user}".format(
site=site.name, user=self.request.user.username
),
"You have been invited by {user} to join {site} community.".format(
user=self.request.user.username, site=site.name
),
settings.DEFAULT_FROM_EMAIL,
[instance.recipient],
)

if (
mail_status
and InviteFriend.objects.filter(sender=self.request.user).count() == 2
):
Points.objects.create(user=self.request.user, score=1)
InviteFriend.objects.filter(sender=self.request.user).delete()

messages.success(
self.request,
"An email has been sent to your friend. Keep inviting your friends and get points!",
)
return HttpResponseRedirect(self.success_url)
context = {
'site_name': site.name,
'sender_username': self.request.user.username,
'referral_link': referral_link,
}
html_content = render_to_string('email/invitation_email.html', context)
text_content = strip_tags(html_content)
subject = f"Invitation to {site.name} from {self.request.user.username}"
from_email = settings.DEFAULT_FROM_EMAIL
to = [instance.recipient]
msg = EmailMultiAlternatives(subject, text_content, from_email, to)
msg.attach_alternative(html_content, "text/html")
msg.send()
# email.send()
# site = get_current_site(self.request)
# referral_link = f"{site.domain}/referral/?ref={instance.referral_code}"

# mail_status = send_mail(
# subject=f"Invitation to {site.name} from {self.request.user.username}",
# message=f"You have been invited by {self.request.user.username} to join {site.name}. Use this link to sign up: {referral_link}",
# from_email=settings.DEFAULT_FROM_EMAIL,
# recipient_list=[instance.recipient],
# fail_silently=False,
# )

# if mail_status:
# messages.success(self.request, "An email has been sent to your friend. Keep inviting your friends and earn rewards!")

messages.success(self.request, "An email has been sent to your friend. Keep inviting your friends and earn rewards!")
return super().form_valid(form)

@login_required(login_url="/accounts/login")
def follow_user(request, user):
Expand Down Expand Up @@ -3735,6 +3758,41 @@ def get_context_data(self, **kwargs):

return context

@receiver(user_signed_up)
def handle_user_signup(request, user, **kwargs):
referral_token = request.session.get('ref')
if referral_token:
try:
invite = InviteFriend.objects.get(referral_code=referral_token)
# also check the signup mail is same as the invite mail or not
if (not invite.signup_completed) and (invite.recipient == user.email):
# Mark the signup as completed
invite.signup_completed = True
invite.save()
# Reward the user who sent the invite with points
reward_sender_with_points(invite.sender)
# Clear the referral token from the session
del request.session['ref']
except InviteFriend.DoesNotExist:
pass

def reward_sender_with_points(sender):
# Create or update points for the sender
points, created = Points.objects.get_or_create(user=sender, defaults={'score': 0})
points.score += 2 # Reward 2 points for each successful referral signup
points.save()

def referral_signup(request):
referral_token = request.GET.get('ref')
# check the referral token is present on invitefriend model or not and if present then set the referral token in the session
if referral_token:
try:
invite = InviteFriend.objects.get(referral_code=referral_token)
request.session['ref'] = referral_token
except InviteFriend.DoesNotExist:
messages.error(request, "Invalid referral token")
return redirect('account_signup')
return redirect('account_signup')

# class CreateIssue(CronJobBase):
# RUN_EVERY_MINS = 1
Expand Down

0 comments on commit e382705

Please sign in to comment.