• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / INT2-Monday-Spring2024-Team-3 / #620224879

07 Apr 2024 07:22PM UTC coverage: 88.945%. First build
#620224879

Pull #163

travis-ci

Pull Request #163: Reviewhistory

5 of 17 new or added lines in 1 file covered. (29.41%)

1416 of 1592 relevant lines covered (88.94%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.32
/backend/views/review_handlers.py
1
import json
1✔
2
import logging
1✔
3
from django.http import JsonResponse, HttpResponseServerError
1✔
4
from django.views.decorators.http import require_POST
1✔
5
from django.contrib.auth.decorators import login_required
1✔
6
from backend.models import (
1✔
7
    Event,
1✔
8
    Review,
1✔
9
    SuspendedUser,
1✔
10
    ReplyToReview,
1✔
11
    Report,
12
    ReportReply,
1✔
13
)
14
from django.shortcuts import get_object_or_404, redirect
1✔
15
from django.db.models import Avg
16
from django.db.models import F
17
from django.core.paginator import Paginator
1✔
18
from django.shortcuts import render
1✔
19

1✔
20
from backend.huggingface import censorbot
1✔
21
from datetime import datetime, timedelta
1✔
22
from backend.admin import send_notification_email
1✔
23

×
24
logger = logging.getLogger(__name__)
25

26

27
@login_required
28
@require_POST
29
def post_review(request, event_id):
1✔
30
    event = get_object_or_404(Event, pk=event_id)
1✔
31
    user = request.user
1✔
32
    if SuspendedUser.objects.filter(user=user, is_suspended=True).exists():
×
33
        return JsonResponse(
34
            {
35
                "success": False,
36
                "message": "Your account is suspended. You cannot post a review.",
37
            }
38
        )
1✔
39
    rating = request.POST.get("rating")
40
    review_text = request.POST.get("review_text")
1✔
41
    # if censorbot.detect_hate_speech(review_text)[0]["label"] == "hate":
42
    #     return JsonResponse(
1✔
43
    #         {
44
    #             "success": False,
1✔
45
    #             "message": "Your review contains hate speech. Please remove it and try again.",
46
    #         }
1✔
47
    #     )
1✔
48
    review = Review(event=event, user=user, rating=rating, review_text=review_text)
1✔
49
    review.likes_count = 0
1✔
50
    review.save()
1✔
51

52
    liked_by_users = review.liked_by.all()
1✔
53

54
    avg_rating_result = Review.objects.filter(event=event).aggregate(Avg("rating"))
55
    new_avg_rating = avg_rating_result["rating__avg"] or 0
56
    new_avg_rating = round(new_avg_rating, 2)
57
    event.avg_rating = new_avg_rating
58
    event.save()
59

60
    return JsonResponse(
61
        {
62
            "success": True,
63
            "review_id": review.id,
64
            "new_avg_rating": new_avg_rating,
65
            "user": {
66
                "username": user.username,
67
                "profile": {
68
                    "avatar": (user.profile.avatar.url if user.profile.avatar else None)
69
                },
70
            },
71
            "rating": review.rating,
72
            "review_text": review.review_text,
73
            "timestamp": review.timestamp.isoformat(),
1✔
74
            "likes_count": review.likes_count,
×
75
            "liked_by": [user.username for user in liked_by_users],
×
76
            "reply_count": review.reply_count,
×
77
        }
×
78
    )
79

×
80

81
def get_average_rating(request, event_id):
82
    reviews = Review.objects.filter(event__id=event_id)
1✔
83
    average_rating = reviews.aggregate(Avg("rating"))["rating__avg"]
×
84
    if average_rating is not None:
×
85
        return JsonResponse({"avg_rating": average_rating})
×
86
    else:
87
        return JsonResponse({"avg_rating": None})
×
88

89

×
90
def get_reviews_for_event(request, event_id):
×
91
    try:
92
        page_number = request.GET.get("page", 1)
×
93
        reviews_per_page = 100
×
94

×
95
        reviews = Review.objects.filter(event__id=event_id).order_by("timestamp")
96

97
        paginator = Paginator(reviews, reviews_per_page)
98
        page_obj = paginator.get_page(page_number)
99

100
        reviews_data = []
101
        for review in page_obj:
102
            reviews_data.append(
103
                {
104
                    "id": review.id,
105
                    "user": {
106
                        "username": review.user.username,
107
                        "profile": {
108
                            "avatar": (
109
                                review.user.profile.avatar.url
110
                                if review.user.profile.avatar
111
                                else None
112
                            )
113
                        },
114
                    },
115
                    "rating": review.rating,
116
                    "review_text": review.review_text,
117
                    "timestamp": review.timestamp.isoformat(),
118
                    "likes_count": review.likes_count,
×
119
                    "liked_by": list(
120
                        review.liked_by.values_list("username", flat=True)
121
                    ),
122
                    "reply_count": review.reply_count,
123
                }
124
            )
125

126
        return JsonResponse(
127
            {
×
128
                "reviews": reviews_data,
×
129
                "has_next": page_obj.has_next(),
×
130
                "next_page_number": (
131
                    page_obj.next_page_number() if page_obj.has_next() else None
132
                ),
1✔
133
            }
1✔
134
        )
1✔
135
    except Exception as e:
×
136
        print(e)
×
137
        return HttpResponseServerError("Server Error: {}".format(e))
×
138

×
139

×
140
@login_required
×
141
@require_POST
142
def like_review(request, event_id, review_id):
143
    review = get_object_or_404(Review, pk=review_id)
1✔
144
    user = request.user
1✔
145
    if review.liked_by.filter(pk=user.pk).exists():
1✔
146
        return JsonResponse(
×
147
            {"error": "You have already liked this review."}, status=400
×
148
        )
×
149
    review.liked_by.add(user)
×
150
    review.likes_count += 1
×
151
    review.save()
×
152
    return JsonResponse({"success": True, "likes_count": review.likes_count})
153

154

1✔
155
@login_required
1✔
156
@require_POST
1✔
157
def unlike_review(request, event_id, review_id):
×
158
    review = get_object_or_404(Review, pk=review_id)
×
159
    user = request.user
×
160
    if not review.liked_by.filter(pk=user.pk).exists():
×
161
        return JsonResponse({"error": "You did not like this review."}, status=400)
×
162
    review.liked_by.remove(user)
×
163
    review.likes_count = max(review.likes_count - 1, 0)
164
    review.save()
165
    return JsonResponse({"success": True, "likes_count": review.likes_count})
1✔
166

1✔
NEW
167

×
NEW
168
@login_required
×
NEW
169
@require_POST
×
NEW
170
def delete_review(request, event_id, review_id):
×
NEW
171
    try:
×
172
        review = get_object_or_404(Review, pk=review_id)
173
        review.delete()
174
        return JsonResponse({"success": True})
175
    except Exception as e:
176
        return JsonResponse({"success": False, "message": str(e)}, status=500)
177

178

179
@login_required
180
def get_user_reviews(request, username):
181
    user = request.user
182
    reviews = Review.objects.filter(user=user).order_by("-timestamp")
183
    reviews_data = []
184
    for review in reviews:
185
        reviews_data.append(
NEW
186
            {
×
187
                "id": review.id,
188
                "event": {
189
                    "title": review.event.title,
1✔
190
                    "location": review.event.location,
1✔
191
                    "id": review.event.id,
1✔
NEW
192
                },
×
NEW
193
                "rating": review.rating,
×
NEW
194
                "review_text": review.review_text,
×
NEW
195
                "timestamp": review.timestamp.isoformat(),
×
NEW
196
                "likes_count": review.likes_count,
×
NEW
197
                "liked_by": list(review.liked_by.values_list("username", flat=True)),
×
198
            }
199
        )
200
    return render(request, "review_history.html", {"reviews": reviews_data})
1✔
201

1✔
202

×
203
@login_required
×
204
@require_POST
×
205
def delete_reviewhistory(request, review_id, username):
206
    try:
207
        review = get_object_or_404(Review, pk=review_id)
208
        review.delete()
209
        return JsonResponse({"success": True})
210
    except Exception as e:
×
211
        return JsonResponse({"success": False, "message": str(e)}, status=500)
×
212

213

×
214
@require_POST
×
215
def reply_to_review(request, event_id, review_id):
216
    user = request.user
217
    if SuspendedUser.objects.filter(user=user, is_suspended=True).exists():
218
        return JsonResponse(
×
219
            {
220
                "success": False,
221
                "message": "Your account is suspended. You cannot post a reply.",
×
222
            }
×
223
        )
×
224
    review = get_object_or_404(Review, pk=review_id)
225
    reply_text = request.POST.get("reply_text")
×
226

227
    if not reply_text:
228
        return JsonResponse(
229
            {"success": False, "message": "Reply text is required."}, status=400
230
        )
231

232
    reply = ReplyToReview.objects.create(
233
        review=review, fromUser=user, toUser=review.user, reply_text=reply_text
234
    )
235
    liked_by_users = reply.liked_by.all()
236
    review.reply_count = F("reply_count") + 1
237
    review.save()
238
    review.refresh_from_db(fields=["reply_count"])
239

240
    return JsonResponse(
241
        {
242
            "success": True,
243
            "reply_id": reply.id,
244
            "reply_text": reply.reply_text,
245
            "from_user": {
246
                "username": reply.fromUser.username,
247
                "profile": {
1✔
248
                    "avatar": (
×
249
                        reply.fromUser.profile.avatar.url
×
250
                        if reply.fromUser.profile.avatar
251
                        else None
252
                    )
×
253
                },
×
254
            },
×
255
            "to_user": review.user.username,
256
            "timestamp": reply.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
257
            "reply_count": review.reply_count,
258
            "likes_count": reply.likes_count,
259
            "likes_by": [user.username for user in liked_by_users],
260
        }
261
    )
262

263

264
def get_replies_for_review(request, event_id, review_id):
265
    try:
266
        replies = ReplyToReview.objects.filter(review__id=review_id).order_by(
267
            "-timestamp"
268
        )
269
        replies_data = []
270

271
        for reply in replies:
272
            replies_data.append(
×
273
                {
274
                    "id": reply.id,
×
275
                    "from_user": {
×
276
                        "username": reply.fromUser.username,
×
277
                        "profile": {
278
                            "avatar": (
279
                                reply.fromUser.profile.avatar.url
280
                                if reply.fromUser.profile.avatar
281
                                else None
282
                            )
283
                        },
284
                    },
285
                    "to_user": reply.toUser.username,
286
                    "reply_text": reply.reply_text,
287
                    "timestamp": reply.timestamp.isoformat(),
288
                    "likes_count": reply.likes_count,
289
                    "liked_by": list(reply.liked_by.values_list("username", flat=True)),
290
                }
291
            )
292
        return JsonResponse({"replies": replies_data})
293

294
    except Exception as e:
295
        print(e)
296
        return HttpResponseServerError("Server Error: {}".format(e))
297

298

299
@login_required
300
@require_POST
301
def like_reply(request, event_id, review_id, reply_id):
302
    replies = ReplyToReview.objects.filter(review__id=review_id)
303
    reply = get_object_or_404(replies, pk=reply_id)
304
    user = request.user
305
    if reply.liked_by.filter(pk=user.pk).exists():
306
        return JsonResponse(
307
            {"error": "You have already liked this review."}, status=400
308
        )
309

310
    reply.liked_by.add(user)
311
    reply.likes_count += 1
312
    reply.save()
313
    return JsonResponse({"success": True, "likes_count": reply.likes_count})
314

315

316
@login_required
317
@require_POST
318
def unlike_reply(request, event_id, review_id, reply_id):
319
    replies = ReplyToReview.objects.filter(review__id=review_id)
320
    reply = get_object_or_404(replies, pk=reply_id)
321
    user = request.user
322
    if not reply.liked_by.filter(pk=user.pk).exists():
323
        return JsonResponse({"error": "You did not like this review."}, status=400)
324

325
    reply.liked_by.remove(user)
326
    reply.likes_count = max(reply.likes_count - 1, 0)
327
    reply.save()
328
    return JsonResponse({"success": True, "likes_count": reply.likes_count})
329

330

331
@login_required
332
@require_POST
333
def delete_reply(request, event_id, review_id, reply_id):
334
    try:
335
        review = get_object_or_404(Review, pk=review_id)
336
        review.reply_count = review.reply_count - 1
337
        review.save()
338
        replies = ReplyToReview.objects.filter(review__id=review_id)
339
        reply = get_object_or_404(replies, pk=reply_id)
340
        reply.delete()
341
        return JsonResponse({"success": True})
342
    except Exception as e:
343
        return JsonResponse({"success": False, "message": str(e)}, status=500)
344

345

346
@login_required
347
@require_POST
348
def report_review(request, review_id, event_id=None):
349
    try:
350
        # Parse JSON data from request body
351
        print(review_id)
352

353
        data = json.loads(request.body)
354
        print(request.body)
355
        review = get_object_or_404(Review, pk=review_id)
356

357
        # Check if the review has already been reported by this user
358
        if Report.objects.filter(review=review, reported_by=request.user).exists():
359
            return JsonResponse(
360
                {"success": False, "message": "You have already reported this review."}
361
            )
362

363
        # Extract title and description from the JSON data
364
        title = data.get("title")
365
        description = data.get("description")
366

367
        # Create a new report
368
        Report.objects.create(
369
            title=title,
370
            description=description,
371
            review=review,
372
            reported_by=request.user,
373
            reported_user=review.user,
374
        )
375
        review.is_reported = True
376
        review.save()
377

378
        subject = "Report Received"
379
        message = "Your report has been received. An admin will review your report and take appropriate action. Thank you for your patience."
380
        send_notification_email(request.user, subject, message)
381

382
        return JsonResponse(
383
            {"success": True, "message": "Report submitted successfully."}
384
        )
385
    except Exception as e:
386
        # Log the error for better debugging
387
        print(f"Error reporting review: {e}")
388
        return JsonResponse({"success": False, "message": str(e)})
389

390

391
@login_required
392
@require_POST
393
def reply_report(request, review_id, reply_id, event_id=None):
394
    try:
395
        # Parse JSON data from request body
396
        print(review_id)
397

398
        data = json.loads(request.body)
399
        print(request.body)
400
        review = get_object_or_404(Review, pk=review_id)
401
        reply = get_object_or_404(ReplyToReview, pk=reply_id)
402
        print(reply)
403

404
        # Check if the reply has already been reported by this user
405
        if ReportReply.objects.filter(reply=reply, reported_by=request.user).exists():
406
            return JsonResponse(
407
                {"success": False, "message": "You have already reported this reply."}
408
            )
409

410
        # Extract title and description from the JSON data
411
        title = data.get("title")
412
        description = data.get("description")
413

414
        # Create a new report
415
        ReportReply.objects.create(
416
            title=title,
417
            description=description,
418
            review=review,
419
            reply=reply,
420
            reported_by=request.user,
421
            reported_user=reply.fromUser,  # assuming reply.user is the one who made the reply
422
        )
423
        reply.is_reported = True
424
        reply.save()
425

426
        subject = "Report Received"
427
        message = "Your report has been received. An admin will review your report and take appropriate action. Thank you for your patience."
428
        send_notification_email(request.user, subject, message)
429

430
        return JsonResponse(
431
            {"success": True, "message": "Report submitted successfully."}
432
        )
433
    except Exception as e:
434
        # Log the error for better debugging
435
        print(f"Error reporting reply: {e}")
436
        return JsonResponse({"success": False, "message": str(e)})
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc