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

Option to remove reminders issue #67 #81

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
34 changes: 33 additions & 1 deletion api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

from django.test import RequestFactory, TestCase

from .views import reminders, eligible_jurisdiction
from .views import reminders, eligible_jurisdiction, unsubscribe
from alerts.models import Alert
from decouple import config


class testReminders(TestCase):
Expand All @@ -17,6 +18,9 @@ def _post(self, url, params):
def _get(self, url, params):
return self.factory.get(url, params)

# def _delete(self, url):
# return self.factory.delete(url)

def testReminderWithArraignmentIn8Days(self):
arraignment_datetime = (datetime.today() + timedelta(days=8)).strftime('%Y-%m-%dT%H:%M:%S')
request = self._post('/api/reminders', {
Expand Down Expand Up @@ -94,3 +98,31 @@ def testEligibleJurisdictions(self):
'seminole', 'sequoyah', 'stephens', 'texas', 'tillman',
'tulsa', 'wagoner', 'washington', 'washita', 'woods',
'woodward']})

def testUnsubscribe(self):
alert = Alert(
when='2020-07-27',
to="+1-000-001-0002",
what="test reminder"
)
alert.save()
self.assertEqual(Alert.objects.filter(to='+1-000-001-0002').count(), 1)

request = self._post('api/unsubscribe/000-001-0002', {
'key': config('SECRET_KEY')
})
response = unsubscribe(request, '000-001-0002')
resp_json = json.loads(response.content)
message = resp_json.get('message', None)
self.assertEqual(message, 'Reminders for 000-001-0002 deleted.')
self.assertEqual(Alert.objects.filter(to='+1-000-001-0002').count(), 0)

def testUnsubsribeNotExists(self):
request = self._post('api/unsubscribe/000-001-0003', {
'key': config('SECRET_KEY')
})
response = unsubscribe(request, '000-001-0003')
resp_json = json.loads(response.content)
message = resp_json.get('message', None)
self.assertEqual(message, 'There are no reminders set for 000-001-0003.')
self.assertEqual(Alert.objects.filter(to='+1-000-001-0003').count(), 0)
1 change: 1 addition & 0 deletions api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
path('case', views.case, name='case'),
path('reminders', views.reminders, name='reminders'),
path('eligible-jurisdiction', views.eligible_jurisdiction, name='eligible_jurisdiction'),
path('unsubscribe/<phone>', views.unsubscribe, name='unsubscribe'),
]
16 changes: 16 additions & 0 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from decouple import config

import oscn

Expand Down Expand Up @@ -104,6 +105,21 @@ def eligible_jurisdiction(request):

return HttpResponse(status=405)

@csrf_exempt
def unsubscribe(request, phone):
key = request.POST.get('key', None)
message =''
if key == config('SECRET_KEY'):
formatted_phone = "+1-" + phone
alerts = Alert.objects.filter(to=formatted_phone)
if not alerts:
message = f"There are no reminders set for {phone}."
else:
alerts.delete()
message = f"Reminders for {phone} deleted."
else:
message = "Unauthorized."
return JsonResponse({'message': message})

def find_arraignment_or_return_False(events):
for event in events:
Expand Down
1 change: 1 addition & 0 deletions website/templates/base_generic.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{% load static %}
<link rel="stylesheet" href="{% static "css/styles.css" %}">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>

<!-- Global site tag (gtag.js) - Google Analytics -->
Expand Down
57 changes: 50 additions & 7 deletions website/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ <h4>FEWER FINES</h4>
<section id="form">
<div class="container text-center">
{% if messages %}
{% for message in messages %}
<p{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</p>
{% for message in messages %}
{% if not message.extra_tags %}
<p{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</p>
{% endif %}
{% endfor %}
{% endif %}
<h2>Fill Out Reminder Form:</h2>
Expand Down Expand Up @@ -130,13 +132,54 @@ <h4>5. When will I be reminded of my court case?</h4>
<h4>6. How often will I be reminded?</h4>
<p>Currently, you will only be reminded once.</p>
</div>
<div class="col-sm-6">
<h4>7. How do I unsubscribe?</h4>
<p></p>
<div class="col-sm-6" id='contact'>
<h4>7. How do I contact the people behind CourtBot?</h4>
<p>You can contact us at <a href="mailto:courtbotmuskogee@gmail.com">courtbotmuskogee@gmail.com.</a></p>
</div>
<div class="col-sm-6">
<h4>8. How do I contact the people behind CourtBot?</h4>
<p>You can contact us at <a href="mailto:courtbotmuskogee@gmail.com">courtbotmuskogee@gmail.com.</a></p>
<h4>8. How do I unsubscribe?</h4>
<p class='mb-0'>Click unsubscribe to remove reminders.</p>
<!-- Dropdown form for unsubscribing -->
<div class="col-sm-6 dropdown mt-0"></div>
<button class="btn btn-sm btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Unsubscribe
</button>
<form class="dropdown-menu p-4" action="/send_verification_code" method="POST">
<div class="form-group">
<small>(ex: 918-123-4567)</small>
<input type="tel" class="form-control" id="remove_phone_num" name="remove_phone_num" placeholder="Enter Phone Number"
pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-sm btn-primary">Remove</button>
</form>
</div>
<!-- Message for unsubscribing response -->
{% if messages %}
{% for message in messages %}
{% if message.extra_tags and message.extra_tags == 'unsubscribe' %}
<p>{{ message }}</p>
{% endif %}
{% endfor %}
{% endif %}

<!-- Displays verification code form if verify message tag exists -->
{% if messages %}
{% for message in messages %}
{% if message.extra_tags and message.extra_tags == 'verify' %}
<p>{{ message }}</p>
<form action="/unsubscribe_reminders" method="POST" id="verify">
<div class="form-group">
<input type="number" class="form-control" id="verification_code" name="verification_code" placeholder="Enter 4 digit code"
pattern="[0-9]{4}" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-sm btn-primary">Submit</button>
</form>
{% endif %}
{% endfor %}
{% endif %}

</div>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion website/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@

urlpatterns = [
path('', views.index, name='index'),
path('schedule_reminders', views.schedule_reminders, name='schedule_reminders')
path('schedule_reminders', views.schedule_reminders, name='schedule_reminders'),
path('unsubscribe_reminders', views.unsubscribe_reminders, name='unsubscribe_reminders'),
path('send_verification_code', views.send_verification_code, name='send_verification_code')
]
46 changes: 45 additions & 1 deletion website/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.shortcuts import render, redirect
from datetime import datetime, timedelta
import re
from random import randint

from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
Expand All @@ -9,15 +10,21 @@

import oscn, requests, json


from alerts.models import Alert

from twilio.rest import Client
from decouple import config

TWILIO_ACCOUNT_SID = config('TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = config('TWILIO_AUTH_TOKEN')
TWILIO_FROM_NUMBER = config('TWILIO_FROM_NUMBER')

def index(request):
# """View function for home page of site."""

# Render the HTML template index.html with the data in the context variable
return render(request, 'index.html')


def check_valid_case(request):
# Process form data and requests arraignment data form api/case
Expand All @@ -42,6 +49,7 @@ def set_case_reminder(arraignment_datetime, case_num, phone_num):
"phone_num": f"+1-{phone_num}"
})
resp = json.loads(reminder_request.content)

if resp.get('error', None):
return False, resp['error']
message = f'Text reminder for case {case_num} occuring on {arraignment_datetime} was scheduled under {phone_num}.'
Expand Down Expand Up @@ -72,5 +80,41 @@ def schedule_reminders(request):
if add_num:
_, another_reminder_message = set_case_reminder(arraignment_datetime, case_num, add_num)
messages.info(request, another_reminder_message)

return redirect('/#form')

@csrf_exempt
def unsubscribe_reminders(request):
code = request.POST['verification_code']
if int(code) == request.session.get('verification_code', None):
phone = request.session.get('phone_number', None)
# request to api for reminder deletion, includes secret key to prevent unauthorized request
remove_request = requests.post(f"http://courtbot-python.herokuapp.com/api/unsubscribe/{phone}", {
"key": config('SECRET_KEY')
})
resp = json.loads(remove_request.content)
messages.info(request, resp.get('message', None), extra_tags='unsubscribe')
del request.session['verification_code']
del request.session['phone_number']
return redirect('/#contact')
else:
messages.error(request, 'Invalid code', extra_tags='verify')
return redirect('/#contact')

@csrf_exempt
def send_verification_code(request):
# Sends random 4 digit code to verify owner of phone number requesting cancellation
phone = request.POST['remove_phone_num']
formatted_phone = '+1-' + phone
code = randint(1000,9999)
# save code and phone number in session for other view function
request.session['verification_code'] = code
request.session['phone_number'] = phone
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
message = client.messages.create(
to=formatted_phone,
from_=TWILIO_FROM_NUMBER,
body=f"Courtbot unsubscribe verification code: {code}"
)
messages.info(request, 'Enter verification code', extra_tags='verify')
return redirect("/#contact")